基本數據:Tensor
Tensor,即張量,是PyTorch中的基本操作對象,可以看成是包含單一數據類型元素的多維矩陣。
一、Tensor數據類型
-
定義:Tensor在使用時可以有不同的數據類型,官方給出了7種CPU Tensor類型和8種GPU Tensor類型,在使用時可以根據網絡模型所需要的精度與顯存容量,合理選取。
-
torch.set_default_tensor_type():設置默認使用的Tensor類型。
torch.set_default_tensor_type('torch.DoubleTensor')
-
Tensor之間類型轉換:通過type(new_type)、type_as()、int()等多種方法操作
import torch torch.set_default_tensor_type('torch.FloatTensor') a = torch.Tensor(2,2) print(a) # 使用double()轉換 b = a.double() print(b) # 使用type() c = a.type(torch.DoubleTensor) print(c) # 使用type_as() d = a.type_as(b) print(b)
二、Tensor的創建與維度查看
-
Tensor的創建有多種方法
import torch # 最基礎的Tensor()函數創建方法 a = torch.Tensor(2,2) print(a) # 使用Python的list序列進行創建 b = torch.Tensor([[1, 2], [3, 4]]) print(b) # 使用zeros()函數,所有元素均爲0,類似的有ones() c = torch.zeros(2, 2) print(c) # 使用eye()函數,對角線均爲1,不要求行列數相同,生成二維矩陣 d = torch.eye(2, 2) print(b) # 使用randn()函數,生成隨機矩陣 e = torch.randn(2, 2) print(e) # 使用arange(start,end,step)函數,表示從start到end,間距爲step的一維向量 f = torch.arange(1, 6, 2) print(f) # 使用linspace(start,end,steps)函數,表示從stat到end,一個steps份的一維向量 g = torch.linspace(1, 7, 3) print(g) # 使用randperm(num)函數,生成長度爲num的隨機排列向量 h = torch.randperm(10) print(h)
輸出:
tensor([[-1.8399e+19, 4.5909e-41], [-1.8399e+19, 4.5909e-41]]) tensor([[1., 2.], [3., 4.]]) tensor([[0., 0.], [0., 0.]]) tensor([[1., 2.], [3., 4.]]) tensor([[4.2157e-04, 8.0940e-01], [5.4407e-01, 7.1835e-01]]) tensor([1, 3, 5]) tensor([1., 4., 7.]) tensor([6, 3, 1, 0, 8, 9, 2, 4, 7, 5])
-
使用Tansor.shape或者size()函數查看每一維的大小,兩者等價
import torch a = torch.Tensor(2, 2) print(a) print(a.shape) print(a.size())
輸出:
tensor([[1.4013e-45, 0.0000e+00], [0.0000e+00, 0.0000e+00]]) torch.Size([2, 2]) torch.Size([2, 2])
-
查看Tensor的元素個數,使用Tensor.numel()或者Tensor.nelement()函數,兩者等價
三、Tensor的組合與分塊
-
組合操作是指將不同的Tensor疊起來,主要有Tensor.cat()和Tensor,stack()兩個函數;
import torch a = torch.Tensor([[1, 2], [3, 4]]) print(a) b = torch.Tensor([[5, 6], [7, 8]]) print(b) # 以第一維進行拼接,變成4x2的矩陣 print(torch.cat([a, b], 0)) # 以第二維進行拼接,變成2x4的矩陣 print(torch.cat([a, b], 1))
輸出:
tensor([[1., 2.], [3., 4.]]) tensor([[5., 6.], [7., 8.]]) tensor([[1., 2.], [3., 4.], [5., 6.], [7., 8.]]) tensor([[1., 2., 5., 6.], [3., 4., 7., 8.]])
-
分塊操作與組合操作相反,指將Tensor分割成不同 子Tensor,主要有tensor.chunk()與tensor.split()兩個函數;
import torch a = torch.Tensor([[1, 2, 3], [4, 5, 6]]) print(a) # 使用chunk,沿0維進行分塊,一共分兩塊,因此分割爲1x3的Tesnsor print(torch.chunk(a, 2, 0)) # 沿1維進行,分割成兩個Tensor,當不能整除的時候,最後一個的維數會小於前面的 # 因此,分割成2x2和2x1的兩個矩陣 print(torch.chunk(a, 2, 1)) # 使用split,沿着第0維,每一維度爲2,由於第1維的維度爲2,因此相當於沒有分割 print(torch.split(a, 2, 0)) # 使用split,沿着第1維,每一維度爲2,分割成2x2和2x1的兩個矩陣 print(torch.split(a, 2, 1))
輸出:
tensor([[1., 2., 3.], [4., 5., 6.]]) (tensor([[1., 2., 3.]]), tensor([[4., 5., 6.]])) (tensor([[1., 2.], [4., 5.]]), tensor([[3.], [6.]])) (tensor([[1., 2., 3.], [4., 5., 6.]]),) (tensor([[1., 2.], [4., 5.]]), tensor([[3.], [6.]]))
四、Tensor的索引
-
索引主要包括下標索引、表達式索引,使用torch.where()和Tensor.clamp()的選擇性索引。
-
下標索引和表達式索引
import torch a = torch.Tensor([[0, 1], [2, 3]]) print(a) # 根據下標進行索引 print(a[1]) print(a[0, 1]) # 選擇a中大於0的元素,返回和a相同大小的Tensor,符合條件的置1,否則置0 print(a > 0) # 選擇非0座標,並返回 print(torch.nonzero(a))
輸出:
tensor([[0., 1.], [2., 3.]]) tensor([2., 3.]) tensor(1.) tensor([[False, True], [ True, True]]) tensor([[0, 1], [1, 0], [1, 1]])
-
torch.where()和Tensor.clamp()
import torch a = torch.Tensor([[0, 1], [2, 3]]) print(a) # torch.where(condition, x, y),滿足condition的位置輸出x,否則輸出y print(torch.where(a > 1, torch.full_like(a, 1), a)) # 對Tensor元素進行限制可以使用clamp()函數,示例如下,限制最小值爲1,最大值爲2 print(a.clamp(1, 2))
輸出:
tensor([[0., 1.], [2., 3.]]) tensor([[0., 1.], [1., 1.]]) tensor([[1., 1.], [2., 2.]])
五、Tensor的變形
-
變形操作是指改變Tensor的維度,以適應在深度學習的計算中,數據維度經常變換的需求。在PyTorch中主要有4類不同的變形方法。
-
view()、resize()和reshape()函數:可以在不改變Tensor數據的前提下任意改變Tensor的形狀,必須保證調整前後的元素個數相同,並且調整前後共享內存,三者的作用基本相同。
import torch a = torch.arange(1, 5) print(a) # 使用view() print(a.view(2, 2)) # 使用resize_() print(a.resize_(4, 1)) # 使用reshape() print(a.reshape(1, 4))
輸出:
tensor([1, 2, 3, 4]) tensor([[1, 2], [3, 4]]) tensor([[1], [2], [3], [4]]) tensor([[1, 2, 3, 4]])
-
transpose()和permute()函數:transpose()函數可以將指定的兩個維度的元素進行轉置, permute()函數則可以按照給定的維度進行變換。
import torch a = torch.randn(2, 2, 2) print(a) # 將0維和1維的元素進行轉置 print(a.transpose(0, 1)) # 按照2、1、0的維度順序重新進行元素排列 print(a.permute(2, 1, 0))
輸出:
tensor([[[-1.5178, 0.9670], [ 0.4453, -1.0351]], [[-0.1473, 0.1650], [-0.1403, 0.0548]]]) tensor([[[-1.5178, 0.9670], [-0.1473, 0.1650]], [[ 0.4453, -1.0351], [-0.1403, 0.0548]]]) tensor([[[-1.5178, -0.1473], [ 0.4453, -0.1403]], [[ 0.9670, 0.1650], [-1.0351, 0.0548]]])
-
squeeze()和unsqueeze()函數:在實際應用中,經常需要增加或減少Tensor的維度。前者用於去除size爲1的維度,而後者則是將指定的維度size變爲1。
import torch a = torch.arange(1, 4) print(a) print(a.shape) print(a.unsqueeze(0)) print(a.unsqueeze(0).shape) print(a.unsqueeze(0).squeeze(0)) print(a.unsqueeze(0).squeeze(0).shape)
輸出:
tensor([1, 2, 3]) torch.Size([3]) tensor([[1, 2, 3]]) torch.Size([1, 3]) tensor([1, 2, 3]) torch.Size([3])
- expand()和expand_as()函數:有時候需要採用複製的形式來擴展Tensor的維度,expand()函數將size爲1的維度擴展爲指定大小,也可以使用expand_as()函數指定。
import torch a = torch.randn(2, 2, 1) print(a) # 將第2維的維度由1變爲3,則複製該維的元素,並擴展爲3 print(a.expand(2, 2, 3))
輸出:
tensor([[[ 0.5300], [ 0.8920]], [[-0.2896], [-0.2523]]]) tensor([[[ 0.5300, 0.5300, 0.5300], [ 0.8920, 0.8920, 0.8920]], [[-0.2896, -0.2896, -0.2896], [-0.2523, -0.2523, -0.2523]]])