1. 程式人生 > 其它 >view和reshape的區別

view和reshape的區別

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(...)