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(...)
posted @ 2022-05-25 18:29  Rclear  阅读(248)  评论(0编辑  收藏  举报