Pytorch
PyTorch
是基於 Python
的科學計算包,目標是兩類人群:
- 使用 GPU 強大的算力對
NumPy
的替代 - 深度學習研究平台提供了最大化的靈活性和速度
Tensors
Tensors
是類似於 NumPy
的 ndarrays
,除此之外, Tensors
還可以被用在 GPU
上用來加快計算。
from __future__ import print_function
import torch
一個未初始化的矩陣被定義,但是在使用之前未包含確定的已知值。當一個未初始化的矩陣被創建時,不管被分配的內存中原來的值是什么都將作為初始值。
構建一個 \(5\times 3\) 的未初始化的矩陣:
x = torch.empty(5, 3)
print(x)
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
構建一個隨機值的矩陣:
x = torch.rand(5, 3)
print(x)
tensor([[0.8347, 0.6374, 0.3601],
[0.5775, 0.6665, 0.5684],
[0.5200, 0.1861, 0.0146],
[0.5582, 0.4759, 0.5131],
[0.9387, 0.2958, 0.1055]])
構建一個數據類型為 long
值全為 0 的矩陣:
x = torch.zeros(5, 3, dtype=torch.long)
print(x)
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
構建一個指定值的張量:
x = torch.tensor([5.5, 3])
print(x)
tensor([5.5000, 3.0000])
或者是創建一個基於已經存在的張量的張量。這個方法將使用輸入張量的屬性,例如數據類型,但是除非新的值被用戶指定
x = x.new_ones(5, 3, dtype=torch.double) # new_* 方法輸入大小
print(x)
x = torch.randn_like(x, dtype=torch.float) # 將覆蓋數據類型
print(x) # 結果有着相同大小
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], dtype=torch.float64)
tensor([[-0.9017, 1.0312, -1.5354],
[ 0.2251, 1.0089, 0.0822],
[-2.0803, -0.0471, 0.3718],
[ 0.6297, 0.5046, -0.5284],
[ 0.4292, -0.8012, -0.4899]])
獲取它的大小:
print(x.size())
torch.Size([5, 3])
torch.Size
是一個元組,所以它支持元組的所有操作
運算符
有很多的運算符語法。在下面的例子中,我們將看一看加法運算符。
加法:語法 1
y = torch.rand(5, 3)
print(x + y)
tensor([[-0.2456, 1.9013, -0.8082],
[ 0.9232, 1.2636, 0.7853],
[-1.0976, 0.6851, 0.7701],
[ 0.9949, 1.0428, 0.4364],
[ 0.8808, 0.0351, -0.3826]])
加法:語法 2
print(torch.add(x, y))
tensor([[-0.2456, 1.9013, -0.8082],
[ 0.9232, 1.2636, 0.7853],
[-1.0976, 0.6851, 0.7701],
[ 0.9949, 1.0428, 0.4364],
[ 0.8808, 0.0351, -0.3826]])
加法:提供一個輸出張量作為參數
result = torch.empty(5, 3)
torch.add(x, y, out=result)
print(result)
tensor([[-0.2456, 1.9013, -0.8082],
[ 0.9232, 1.2636, 0.7853],
[-1.0976, 0.6851, 0.7701],
[ 0.9949, 1.0428, 0.4364],
[ 0.8808, 0.0351, -0.3826]])
加法:in-place
# 將 x 加到 y 上
y.add_(x)
print(y)
tensor([[-0.2456, 1.9013, -0.8082],
[ 0.9232, 1.2636, 0.7853],
[-1.0976, 0.6851, 0.7701],
[ 0.9949, 1.0428, 0.4364],
[ 0.8808, 0.0351, -0.3826]])
任何一個在原張量的內存上修改(in-place)的運算符都有一個后綴
_
。舉個例子,x.copy_()
,x.t_()
都將修改在x
上。
你可以使用標准類 NumPy 的花里胡哨的索引。
print(x[:, 1])
tensor([ 1.0312, 1.0089, -0.0471, 0.5046, -0.8012])
修改維度:如果你想重新修改張量的大小或形狀,可以使用 torch.view
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8) # -1 表示根據其它維度自動推斷
print(x.size(), y.size(), z.size())
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])
如果你只有一個元素的張量,使用 .item()
可以獲得 Python 的數值。
x = torch.randn(1)
print(x)
print(x.item())
tensor([0.9397])
0.9397323131561279
稍后閱讀:還有一百多種運算符,包括轉置、索引、切片、數學運算符、線性代數、隨機數等等,都可以在官方文檔中查看。
NumPy 橋
將 Torch 的張量轉換成 NumPy 的數組是很容易的,反之亦然。
Torch 的張量和 NumPy 的數組將會共享內存(Torch 的張量在 CPU),改變其中的一個就會改變另一個。
將 Torch 的 Tensor 轉換成 NumPy 數組
a = torch.ones(5)
print(a)
tensor([1., 1., 1., 1., 1.])
b = a.numpy()
print(b)
[1. 1. 1. 1. 1.]
觀察 NumPy 數組如何改變值。
a.add_(1)
print(a)
print(b)
tensor([2., 2., 2., 2., 2.])
[2. 2. 2. 2. 2.]
將 NumPy 數組轉換成 Torch 張量
觀察 NumPy 數組的改變,Torch 的 張量自動地隨之改變。
import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a)
print(b)
[2. 2. 2. 2. 2.]
tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
所有在 CPU 上的張量除了 CharTensor 都支持和 NumPy 的來回轉換。
CUDA Tensors
張量可以使用 .to
方法移動到任何一塊設備上。
# 將使用 torch.device 對象移動張量在 GPU 上來回進入
if torch.cuda.is_available():
device = torch.device("cuda") # 一個 CUDA 設備對象
y = torch.ones_like(x, device=device) # 直接創建在 GPU 上
x = x.to(device) # 也可以直接使用字符串 .to("cuda")
z = x + y
print(z)
print(z.to("cpu", torch.double)) # .to 方法也可以修改數據類型