* torch.Tensor 存儲和變換數據的工具
* Tensor與Ndarray多維數組類似,可提供GPU計算和自動求梯度
* 標量:0緯張量,一個數字
* 向量:1緯張量,[ ]
* 矩陣:2緯張量,[ [ ] ]
首先導入torch,查看版本號
import torch #打印torch版本 print(torch.__version__) #查看是否支持GPU torch.cuda.is_avaliable()
代碼運行后的結果是: 1.4.0 True
1.創建Tensor
1.11 直接創建
* torch.tensor(value)
* value:可以是任何維度的張量
print("創建一個標量5") x = torch.tensor(5) print("創建一個向量[]") y = torch.tensor([2,3]) print("創建一個矩陣[ [ ] ]") z = torch.tensor([[1,2], [2,3]]) print(x) print(y) print(z)
輸出結果是: 創建一個標量5 創建一個向量[] 創建一個矩陣[ [ ] ] tensor(5) tensor([2, 3]) tensor([[1, 2], [2, 3]])
1.2使用方法創建
* torch.empty(shape,dtype = type):創建未初始化的Tensor,可指定數據類型,dtype參數可省略
* torch.rand(shape) :創建隨機矩陣
* torch.zeros(shape):創建0矩陣
* 創建維度均為2緯矩陣
print("創建二維未初始化矩陣") A = torch.empty((2,2)) print(A) print("創建隨機矩陣") B = torch.rand((2,2)) print(B) print("創建0矩陣") C = torch.zeros((2,2)) print(C)
輸出結果是: 創建二維未初始化矩陣 tensor([[ 0.0000e+00, 1.4279e+00], [-9.3980e-11, 4.5908e-41]]) 創建隨機矩陣 tensor([[0.3857, 0.0058], [0.1388, 0.9339]]) 創建0矩陣 tensor([[0., 0.], [0., 0.]])
1.3通過現有的Tensor創建
* matrix.new_ones(shape,dtype) 可以改變維度
* torch.randn_like(matirx,dtype)
print("將原本2*2未初始化矩陣進行重新創建") B = B.new_ones(5,3) print(B) print("將原本2*2未初始化矩陣進行重新創建") A = torch.randn_like(A, dtype = torch.float) print(A)
輸出結果是: 將原本2*2未初始化矩陣進行重新創建 tensor([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.]]) 將原本2*2未初始化矩陣進行重新創建 tensor([[ 0.1454, -0.1173], [-0.7503, 0.5255]])
1.4Tensor的基本方法
* matrix.shape: 獲取Tensor形狀
* matirx.size():獲取Tensor形狀 返回一個tuple,支持tuple的所有操作
print("獲取B矩陣形狀") print(B.shape) print(B.size())
輸出結果是: 獲取B矩陣形狀 torch.Size([5, 3]) torch.Size([5, 3])
2 Tensor操作
2.1 算法操作
2.11 加法操作
* matrix1 + matirx2
* torch.add(matrix1, matrix2, out = A) out指定輸出參數,可省略
* inplace matrix1.add_(matrix2) == (matirx1 += matrix2)
print("使用 + 完成加法操作") print(A + C) print("使用torch.add完成加法操作") print(torch.add(A,C)) print("使用inplace完成加法操作") print(C.add_(A))
輸出結果是: 使用 + 完成加法操作 tensor([[ 0.1454, -0.1173], [-0.7503, 0.5255]]) 使用torch.add完成加法操作 tensor([[ 0.1454, -0.1173], [-0.7503, 0.5255]]) 使用inplace完成加法操作 tensor([[ 0.1454, -0.1173], [-0.7503, 0.5255]])
2.1.2 索引
* 類似於Numpy
* 索引結果與原數據共享內存
A = torch.rand(5,5) print('查看創建Tensor') print(A[1][1]) A[1][1] = 5 print("查看A矩陣第一行第一列是否為5") print(A[1][1])
輸出結果是: 查看創建Tensor tensor(0.6124) 查看A矩陣第一行第一列是否為5 tensor(5.)
2.1.3 改變形狀
* marix.clone() 克隆新副本,解決共享內存帶來的問題
* matrix.view(shape) view() 前后共享data
* matrix.reshape(shape)
#查看clone與變量賦值的區別 print("查看A變量地址") print(id(A)) A_cl = A.clone() print('查看克隆新副本地址') print(id(A_cl)) A_an = A print('查看變量重新賦值后的地址') print(id(A_an))
輸出結果是: 查看A變量地址 2337547400576 查看克隆新副本地址 2337538344512 查看變量重新賦值后的地址 2337547400576
note:這里主要是解釋共享data的問題。直接view()的話維度改變,操作的是同一內存的數據。不會生成新的維度的數據。
* 變量賦值相當於引用,地址不變,只想同一塊內存
* clone()操作會重新申請內存空間
* matrix.item() 將標量Tensor轉化為number
* https://pytorch.org/docs/stable/tensors.html Tensor操作鏈接
2.1.4 Tensor的廣播機制
* 自動使得運算的Tensor相同的操作
* 首先會比較最靠右的維度,如果最靠右的維度相等或其中一個為 1,則認為此維度相等;
* 再繼續向左比較,如果一直滿足,則認為兩者兼容;
* 最后,分別在對應維度上發生廣播,以此補齊直到維度一致;
x = torch.rand(4 , 6) y = torch.rand(4, 1) print(torch.add(x , y))
輸出結果是: tensor([[0.6108, 0.1842, 0.9873, 0.9042, 0.2456, 0.4298], [1.0251, 0.6726, 1.2724, 1.2861, 1.1256, 0.5654], [1.0223, 0.3473, 0.5952, 0.3701, 0.4500, 0.4993], [0.0542, 0.9524, 0.1668, 0.5762, 0.0671, 0.4689]])
2.1.5 Tensor與Numpy的相互轉換
* tensor.numpy() 可將Tensor轉為ndarray數據
a = torch.rand(3,2) print(id(a)) b = a.numpy() print(id(b)) print(a) print(b)
輸出結果為: 2337547166400 2337547429088 tensor([[0.3145, 0.9862], [0.7604, 0.9342], [0.3104, 0.7312]]) [[0.31446308 0.9861587 ] [0.7603721 0.9341993 ] [0.31042498 0.73123205]]
Numpy轉為Tensor
* torch.from_numpy(array)
* torch.Tensor()
import numpy as np c = torch.from_numpy(b) d = torch.Tensor(b) print(type(c)) print(type(d))
<class 'torch.Tensor'> <class 'torch.Tensor'>
2.1.6 Tensor on GPU
* .to("cuda") 將Tensor在GPU上運算
x.to("cuda")
* .to(device) 將Tensor在GPU運算
torch.device("cuda")
x.to(device)
* .to("cpu") 將Tensor在CPU上運算
驗證GPU的運算速度
%%time #jupyter notebook中的魔法語句,可以輸出當前代碼塊的運行速度 print("使用device") device = torch.device("cuda") x = torch.rand(200,100).to(device) y = torch.rand(200,100).to(device) print(x + y)
輸出結果是: 使用device tensor([[1.3311, 1.7433, 1.1089, ..., 0.8775, 1.1430, 0.4877], [1.1953, 0.3628, 0.6479, ..., 0.4781, 0.9154, 1.3447], [1.2134, 0.5482, 1.7713, ..., 0.9025, 1.1786, 0.2083], ..., [0.9276, 0.8605, 0.9905, ..., 0.9992, 1.1613, 0.8636], [1.2191, 0.6350, 0.9921, ..., 1.7540, 1.0139, 1.2921], [1.2137, 0.9510, 0.9126, ..., 0.8433, 0.5871, 1.0881]], device='cuda:0') Wall time: 6.45 s
驗證CPU運算速度
%%time print("使用CPU") x = torch.rand(200,100).to("cpu") y = torch.rand(200,100).to("cpu") print(x + y)
輸出結果是: 使用CPU tensor([[1.4920, 1.1891, 0.0936, ..., 0.5056, 1.6395, 1.0162], [1.4211, 0.9837, 1.1501, ..., 1.2990, 0.7121, 0.3505], [1.1503, 1.0263, 1.4055, ..., 0.6856, 0.3320, 0.7620], ..., [0.4615, 1.0520, 1.3409, ..., 1.1014, 1.0806, 0.9630], [0.9770, 1.4159, 1.6652, ..., 0.9515, 1.2479, 1.2459], [0.7622, 0.9159, 0.9734, ..., 0.5249, 0.1216, 0.6906]]) Wall time: 112 ms
查看同樣維度矩陣計算GPU與CPU的速度差異
print("GPU 比 CPU 的運算速度塊: %.2f 倍" %(112 / 6.45))
輸出結果是:
GPU 比 CPU 的運算速度塊: 17.36 倍