view和reshape的區別
阿新 • • 發佈:2022-05-25
view
view操作主要是返回一個新的shape的檢視,主要是改變原儲存資料的索引方式,原地改變原儲存區而不申請新的空間,前提是資料是連續的。否則要先使用contiguous()方法開闢新的儲存區將其轉化為連續的。
reshape
view可以做的,其實reshape都可以做。reshape對於如果是連續的資料那麼就建立一個新的檢視,否則就申請新的空間使其資料滿足新的shape。
那麼如何區分是否連續呢?
首先,明確一點,無論是python還是C or C++ or Java,其申請的陣列資料在記憶體中都是線性分佈的。
tensor中的size
你可以理解為tensor中每個維度的長度
tensor中的stride
對於pytorch中的tensor來說,其在資訊區儲存了stride變數,這個變數記錄的是跳轉至下一個維度需要跨多少步,與卷積操作的stride不同,注意區分。
連續條件:
滿足以下條件則說明tensor是連續的,可以進行view操作,不必開闢新的空間。
\[stride[i]=stride[i+1] \times size[i+1] \]比如說二維的一個5行4列的一個向量,那麼stride=[4,1],也就是說從第某行到下一行需要跨4步才能到下一行的同一列的位置,而從某一列到下一列只需要跨越一步即可。
舉個例子:
輔助理解tensor裡的stride
import torch a = torch.arange(9).reshape(3, 3) # 初始化張量a b = a.permute(1, 0) # 對a進行轉置 print('struct of a:\n', a) print('size of a:', a.size()) # 檢視b的shape print('stride of a:', a.stride()) # 檢視b的stride print('struct of b:\n', b) print('size of b:', b.size()) # 檢視b的shape print('stride of b:', b.stride()) # 檢視b的stride ########### 執行結果 ########### struct of a: tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) size of a: torch.Size([3, 3]) stride of a: (3, 1) # 注:滿足連續性條件 struct of b: tensor([[0, 3, 6], [1, 4, 7], [2, 5, 8]]) size of b: torch.Size([3, 3]) stride of b: (1, 3) # 注:此時不滿足連續性條件!!!
如上圖所示,對tensor進行轉置或是其他改變shape的操作,若是使得stride和size與原tensor不相容,即不滿足連續條件。
不滿足連續如何使用view呢?
答案在第一節已經說了,使用contiguous()即可
such as:
a.contiguous().view(...)