淺談pytorch中stack和cat的及to_tensor的坑
初入計算機視覺遇到的一些坑
1.pytorch中轉tensor
x=np.random.randint(10,100,(10,10,10)) x=TF.to_tensor(x) print(x)
這個函數會對輸入數據進行自動歸一化,比如有時候我們需要將0-255的圖片轉為numpy類型的數據,則會自動轉為0-1之間
2.stack和cat之間的差別
stack
x=torch.randn((1,2,3)) y=torch.randn((1,2,3)) z=torch.stack((x,y))#默認dim=0 print(z.shape) #torch.Size([2, 1, 2, 3])
所以stack的之後的數據也就很好理解瞭,z[0,…]的數據是x,z[1,…]的數據是y。
cat
z=torch.cat((x,y)) print(z.size()) #torch.Size([2, 2, 3])
cat之後的數據 z[0,:,:]是x的值,z[1,:,:]是y的值。
其中最關鍵的是stack之後的數據的size會多出一個維度,而cat則不會,有一個很簡單的例子來說明一下,比如要訓練一個檢測模型,label是一些標記點,eg:[x1,y1,x2,y2]
送入網絡的加上batchsize則時Size:[batchsize,4],如果我已經有瞭兩堆數據,data1:Size[128,4],data2:Size[128,4],需要將這兩個數據合在一起的話目標data:Size[256,4]。
顯然我們要做的是:torch.cat((data1,data2))
如果我們的數據是這樣:有100個label,每一個label被放進一個list(data)中,[[x1,y1,x2,y2],[x1,y1,x2,y2],…]其中data是一個list長度為100,而list中每一個元素是張圖片的標簽,size為[4]我們需要將他們合一起成為一Size:[100,4]的的數據。
顯然我們要做的是torch.stack(data)。而且torch.stack的輸入參數為list類型!
補充:pytorch中的cat、stack、tranpose、permute、unsqeeze
pytorch中提供瞭對tensor常用的變換操作。
cat 連接
對數據沿著某一維度進行拼接。cat後數據的總維數不變。
比如下面代碼對兩個2維tensor(分別為2*3,1*3)進行拼接,拼接完後變為3*3還是2維的tensor。
代碼如下:
import torch torch.manual_seed(1) x = torch.randn(2,3) y = torch.randn(1,3) print(x,y)
結果:
0.6614 0.2669 0.0617
0.6213 -0.4519 -0.1661
[torch.FloatTensor of size 2×3]-1.5228 0.3817 -1.0276
[torch.FloatTensor of size 1×3]
將兩個tensor拼在一起:
torch.cat((x,y),0)
結果:
0.6614 0.2669 0.0617
0.6213 -0.4519 -0.1661
-1.5228 0.3817 -1.0276
[torch.FloatTensor of size 3×3]
更靈活的拼法:
torch.manual_seed(1) x = torch.randn(2,3) print(x) print(torch.cat((x,x),0)) print(torch.cat((x,x),1))
結果
// x
0.6614 0.2669 0.0617
0.6213 -0.4519 -0.1661
[torch.FloatTensor of size 2×3]// torch.cat((x,x),0)
0.6614 0.2669 0.0617
0.6213 -0.4519 -0.1661
0.6614 0.2669 0.0617
0.6213 -0.4519 -0.1661
[torch.FloatTensor of size 4×3]// torch.cat((x,x),1)
0.6614 0.2669 0.0617 0.6614 0.2669 0.0617
0.6213 -0.4519 -0.1661 0.6213 -0.4519 -0.1661
[torch.FloatTensor of size 2×6]
stack,增加新的維度進行堆疊
而stack則會增加新的維度。
如對兩個1*2維的tensor在第0個維度上stack,則會變為2*1*2的tensor;在第1個維度上stack,則會變為1*2*2的tensor。
見代碼:
a = torch.ones([1,2]) b = torch.ones([1,2]) c= torch.stack([a,b],0) // 第0個維度stack
輸出:
(0 ,.,.) =
1 1(1 ,.,.) =
1 1
[torch.FloatTensor of size 2x1x2]
c= torch.stack([a,b],1) // 第1個維度stack
輸出:
(0 ,.,.) =
1 1
1 1
[torch.FloatTensor of size 1x2x2]
transpose ,兩個維度互換
代碼如下:
torch.manual_seed(1) x = torch.randn(2,3) print(x)
原來x的結果:
0.6614 0.2669 0.0617
0.6213 -0.4519 -0.1661
[torch.FloatTensor of size 2×3]
將x的維度互換
x.transpose(0,1)
結果
0.6614 0.6213
0.2669 -0.4519
0.0617 -0.1661
[torch.FloatTensor of size 3×2]
permute,多個維度互換,更靈活的transpose
permute是更靈活的transpose,可以靈活的對原數據的維度進行調換,而數據本身不變。
代碼如下:
x = torch.randn(2,3,4) print(x.size()) x_p = x.permute(1,0,2) # 將原來第1維變為0維,同理,0→1,2→2 print(x_p.size())
結果:
torch.Size([2, 3, 4])
torch.Size([3, 2, 4])
squeeze 和 unsqueeze
常用來增加或減少維度,如沒有batch維度時,增加batch維度為1。
squeeze(dim_n)壓縮,減少dim_n維度 ,即去掉元素數量為1的dim_n維度。
unsqueeze(dim_n),增加dim_n維度,元素數量為1。
上代碼:
# 定義張量 import torch b = torch.Tensor(2,1) b.shape Out[28]: torch.Size([2, 1]) # 不加參數,去掉所有為元素個數為1的維度 b_ = b.squeeze() b_.shape Out[30]: torch.Size([2]) # 加上參數,去掉第一維的元素為1,不起作用,因為第一維有2個元素 b_ = b.squeeze(0) b_.shape Out[32]: torch.Size([2, 1]) # 這樣就可以瞭 b_ = b.squeeze(1) b_.shape Out[34]: torch.Size([2]) # 增加一個維度 b_ = b.unsqueeze(2) b_.shape Out[36]: torch.Size([2, 1, 1])
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- pytorch下的unsqueeze和squeeze的用法說明
- pytorch tensor計算三通道均值方式
- 人工智能學習Pytorch教程Tensor基本操作示例詳解
- PyTorch中Tensor和tensor的區別及說明
- Python深度學習之Pytorch初步使用