Pytorch張量操作


1.數據類型

如何表示string?

  • One-hot         [0,1,0,0,...]
  • Embedding    Word2vec,glove

類型推斷

1 #type check
2 a=torch.randn(2,3)       
3 print(a.type())                            #torch.FloatTensor
4 print(type(a))                             #<class 'torch.Tensor'>  這種情況比較少
5 print(isinstance(a, torch.FloatTensor))    #True

標量

1 #標量 dimension 0/rank 0(常用於loss)
2 b=torch.tensor(1.3)
3 print(b)                 #tensor(1.3000)
4 print(b.shape)           #torch.Size([])  成員
5 print(len(b.shape))      #0
6 print(b.size())          #torch.Size([])  成員函數

張量

 1 #張量 dimension 1(常用於bias)
 2 print(torch.tensor([1.1]))    #tensor([1.1000]) 指定具體數據,可以是N維
 3 print(torch.FloatTensor(1))   #tensor([9.6429e-39]) 指定具體維度,隨機初始化
 4 data=np.ones(2)
 5 print(torch.from_numpy(data)) #tensor([1., 1.], dtype=torch.float64) 從numpy引入
 6 
 7 c=torch.ones(2)
 8 print(c.shape)                #torch.Size([2])
 9 
10 #張量 dimension 2
11 d=torch.randn(2,3)
12 print(d)
13 #tensor([[-1.8543, -0.7280,  0.6671],
14 #        [ 1.1492, -0.6379, -0.4835]])
15 print(d.shape)          #torch.Size([2, 3])
16 print(d.shape[0])       #2
17 print(d.size(1))        #3    
18 
19 #張量 dimension 3
20 f=torch.rand(1,2,3)
21 print(f)
22 #tensor([[[0.3690, 0.5702, 0.2382],
23 #         [0.3130, 0.5591, 0.3829]]])
24 print(f.shape)         #torch.Size([1, 2, 3])
25 print(f[0])            #取第一個維度
26 #tensor([[0.4535, 0.4307, 0.6469],
27 #        [0.1591, 0.0778, 0.4489]])
28 print(f[0][1])         #tensor([0.1591, 0.0778, 0.4489])

四維適合表示圖片類型

eg:a=torch.rand(b,c,h,w)表示b張c通道、h*w的圖片

1 a=torch.rand(2,3,28,28)
2 print(a.numel())       #4704 全部元素個數
3 print(a.dim())         #4 維度數量 

2.創建Tensor

 1 #方法一:import from numpy
 2 a=np.ones([2,3])
 3 print(torch.from_numpy(a))
 4 #tensor([[1., 1., 1.],
 5 #        [1., 1., 1.]], dtype=torch.float64)
 6 
 7 #方法二:import from List
 8 print(torch.tensor([[2.,3.2],[1.,22.3]]))
 9 #tensor([[ 2.0000,  3.2000],
10 #        [ 1.0000, 22.3000]])

Tip:torch.tensor接受現成的數據

         torch.Tensor/torch.FloatTensor接受shape或者現成的數據

未初始化的方法(作為容器,要用其他類型把數據覆蓋掉):

  • torch.empty()
  • torch.FlostTensor(d1,d2,d3)
  • torch.IntTensor(d1,d2,d3)
1 #設置默認類型
2 print(torch.tensor([1.2,3]).type())               #torch.FloatTensor(不設定的話,默認值)
3 torch.set_default_tensor_type(torch.DoubleTensor)
4 print(torch.tensor([1.2,3]).type())               #torch.DoubleTensor

隨機初始化

1 #rand [0,1]
2 a=torch.rand(2,2)
3 print(a)
4 print(torch.rand_like(a))         #根據a的形狀生成,也可用dtype指定新類型
5 
6 #randint [min,max)不包含max
7 print(torch.randint(1,10,[3,3]))  #第1個參數是min,第二個參數是max,第三個參數是shape

正態分布

1 #正態分布
2 print(torch.randn(3,3))         #N(0,1)
3 print(torch.normal(mean=torch.full([10],0),std=torch.arange(1,0,-0.1)))    #normal得到的維度為1
4 #tensor([ 0.1445, -0.5133, -0.5565,  0.0831,  0.1350,  0.1023, -0.6264, -0.1651, 0.2856,  0.0187])

其他

 1 #ones全1,zeros全0,eye對角,ones_like
 2 print(torch.full([2,3],7))             #第一個參數是shape,第二個參數是value
 3 #tensor([[7., 7., 7.],
 4 #        [7., 7., 7.]])
 5 print(torch.full([], 7))               #tensor(7.) 生成標量
 6 
 7 #生成 [0,n-1]的等差數列
 8 print(torch.arange(0,10,2))            #tensor([0, 2, 4, 6, 8])
 9 
10 #[0,10]等間距切割成steps份
11 print(torch.linspace(0, 10, steps=6))  #tensor([ 0.,  2.,  4.,  6.,  8., 10.])
12 print(torch.logspace(0, 1, steps=5))   #tensor([ 1.0000,  1.7783,  3.1623,  5.6234, 10.0000])
13 
14 
15 #randperm
16 print(torch.randperm(10))             #tensor([8, 5, 2, 4, 7, 1, 3, 9, 6, 0])
17 
18 a=torch.rand(2, 3) 
19 idx=torch.randperm(2)
20 print(idx)                            #tensor([1, 0])
21 print(a[idx])
22 #tensor([[0.6159, 0.9362, 0.5502],
23 #        [0.9774, 0.6772, 0.2909]])

3.索引與切片

1 #切片與索引
2 a=torch.rand(4,3,28,28)
3 print(a[0].shape)               #torch.Size([3, 28, 28])
4 print(a[0,0].shape)             #torch.Size([28, 28])
5 print(a[0,0,2,4])               #tensor(0.7309)
6 
7 print(a[:2,:1].shape)           #torch.Size([2, 1, 28, 28])  等價於a[:2,:1,:,:].shape
8 print(a[:,:,::2,::2].shape)     #torch.Size([4, 3, 14, 14])

使用特定索引index_select

1 #select by specific index
2 print(a.index_select(2, torch.arange(8)).shape)  #torch.Size([4, 3, 8, 28])  第1個參數表示維度,第2個參數表示索引號(Tensor類型)
3 #...表示任意多的維度
4 print(a[0,...].shape)           #torch.Size([3, 28, 28])
5 print(a[:,1,...].shape)         #torch.Size([4, 28, 28]) 

使用掩碼索引masked_select

1 #select by mask
2 x=torch.randn(3,4)
3 mask=x.ge(0.5)                  #greater equal大於等於
4 print(mask)
5 #tensor([[False,  True, False, False],
6 #        [ True, False, False,  True],
7 #        [ True, False,  True, False]])
8 torch.masked_select(x, mask)    #tensor([1.1361, 0.5963, 0.6286, 0.5664, 0.5152]) 維度為1

take索引(在原來Tensor的shape基礎上打平,然后在打平后的Tensor上進行索引)

1 #select by flatten index
2 src=torch.tensor([[4, 3, 5],[6, 7, 8]])
3 print(torch.take(src,torch.tensor([0, 2, 5])))  #tensor([4, 5, 8])

4.維度變換

 reshape/view可以調整Tensor的shape,返回一個新shape的Tensor

1 a=torch.rand(4,1,28,28)
2 print(a.view(4,28*28).shape)        #torch.Size([4, 784])
3 print(a.reshape(4*28,28).shape)     #torch.Size([112, 28])

unsqueeze(index)增加維度

index的范圍[-a.dim()-1,a.dim()+1)    eg.a的維度=4,范圍是[-5,5)

新增加的這一個維度不會改變數據本身,只是為數據新增加了一個組別,這個組別是什么由我們自己定義。

 1 a=torch.rand(4,1,28,28)
 2 print(a.unsqueeze(0).shape)         #torch.Size([1, 4, 1, 28, 28]
 3 
 4 b=torch.tensor([1.2, 2.3])          #torch.Size([2])
 5 print(b.unsqueeze(0))               #tensor([[1.2000, 2.3000]])   torch.Size([2, 1])
 6 print(b.unsqueeze(-1)) 
 7 #tensor([[1.2000],
 8 #        [2.3000]])
 9 
10 x=torch.rand(32)
11 y=torch.rand(4,32,14,14)
12 x=x.unsqueeze(1).unsqueeze(2).unsqueeze(0)      #[32]->[32,1]->[32,1,1]->[1,32,1,1]
13 print(x.shape)                                  #torch.Size([1, 32, 1, 1])) 再進行擴展即可計算x+y 

squeeze(index)刪減維度,刪除size=1的維度

1 a=torch.rand(1,32,1,1)
2 print(a.squeeze().shape)             #torch.Size([32])  不指定維度就擠壓全部
3 print(a.squeeze(0).shape)            #torch.Size([32, 1, 1])
4 print(a.squeeze(-1).shape)           #torch.Size([1, 32, 1])
5 print(a.squeeze(1).shape)            #torch.Size([1, 32, 1, 1])  size不等於1,刪減不了

expand維度擴展:broadcasting(只是改變了理解方式,並沒有增加數據)

某個size=1的維度上擴展size

1 x=torch.rand(32)
2 y=torch.rand(4,32,14,14)
3 x=x.unsqueeze(1).unsqueeze(2).unsqueeze(0)      #[32]->[32,1]->[32,1,1]->[1,32,1,1]
4 print(x.shape)                                  # torch.Size([1, 32, 1, 1])
5 
6 print(x.expand(4,32,14,14).shape)               #torch.Size([4, 32, 14, 14])
7 print(x.expand(-1,32,3,-1).shape)               #torch.Size([1, 32, 3, 1])  -1指該維度不變
8 
9 print((x.expand(4,32,14,14)+y).shape)           #torch.Size([4, 32, 14, 14])

repeat維度重復:memory copied(增加了數據)

repeat會重新申請內存空間,repeat()參數表示各個維度指定的重復次數。

1 a=torch.rand(1,32,1,1)
2 print(a.repeat(4,32,1,1).shape)                 #torch.Size([4, 1024, 1, 1])
3 print(a.repeat(4,1,1,1).shape)                  #torch.Size([4, 32, 1, 1])

轉置操作

.t操作指適用於矩陣

1 a=torch.rand(3, 4)
2 print(a.t().shape)                             #torch.Size([4, 3])

transpose維度交換

1 a=torch.rand(4,3,32,32)
2 b=a.transpose(1, 3).contiguous().view(4,3*32*32).view(4,32,32,3).transpose(1, 3)               
3 #[b,c,h,w]->[b,w,h,c]->[b,whc]->[b,w,h,c]->[b,c,h,w]  展開時按原來的順序展開whc對應32,32,3
4 print(torch.all(torch.eq(a,b)))                       #tensor(True)

permute

四個維度表示的[batch,channel,h,w] ,如果想把channel放到最后去,形成[batch,h,w,channel],那么如果使用前面的維度交換,至少要交換兩次(先13交換再12交換)。而使用permute可以直接指定維度新的所處位置,更加方便。

1 b=torch.rand(4,3,28,32)
2 print(b.transpose(1, 3).shape)                      #torch.Size([4, 32, 28, 3])
3 print(b.transpose(1, 3).transpose(1, 2).shape)      #torch.Size([4, 28, 32, 3])
4 
5 print(b.permute(0,2,3,1).shape)                     #torch.Size([4, 28, 32, 3]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM