引入:view和reshape有什么区别
view
返回的是视图,而reshape
一般返回拷贝(取决于原始张量的存储方式)
视图:共享底层数据
view
只能用于满足连续性张量的视图
问题1:什么叫满足连续性的张量
连续性条件的含义是,张量底层一维数组元素的存储顺序与张量按行优先一维展开的元素顺序是否一致。
>>> x = torch.arange(12).reshape(3,4)
>>> x
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
这个张量是连续的,因为它的底层数据的存储顺序是[0, 1, 2, … , 11],与它按行优先一维展开的顺序相同。
问题2:如何判断一个张量是否满足连续性条件
-
y.is_contiguous()
,True
说明连续 -
y.stride()
,如果stride与y
的形状不匹配,说明不连续例如
>>> x = torch.arange(6).reshape(2,3) >>> x tensor([[0, 1, 2], [3, 4, 5]]) >>> x.stride() (3, 1) >>> y = x.transpose(0,1) # 转置之后不再满足连续性 >>> y tensor([[0, 3], [1, 4], [2, 5]]) >>> y.is_contiguous() False >>> y.stride() (1, 3)
y
按行展开的stride应该是(2, 1)
,所以y
不连续(不满足问题1)
问题3:为什么有些操作需要连续的张量
因为有些操作在底层实现的时候,需要按照一定的顺序访问或修改张量的元素,而不连续的张量会导致这些操作变得复杂或低效。
回到引入,为什么
view
只能用于满足连续性张量的视图?因为它的作用是在不改变底层数据的情况下,使用新的形状查看张量。如果张量不是连续的,那么它的底层数据的存储顺序与它按行优先一维展开的顺序不同,这样就无法用一个新的步长来实现形状的变化
方法1:不连续的张量转成连续张量
接着上一个代码段,调用contiguous()
函数即可
>>> z = y.contiguous() # 将不连续张量y转成连续张量
>>> z
tensor([[0, 3],
[1, 4],
[2, 5]])
>>> z.is_contiguous() # z连续
True
>>> z.stride()
(2, 1)
问题4:为什么reshape可能会返回一个视图或者一个拷贝
reshape
会根据原始张量的内存布局来决定是否可以通过修改步长来实现形状的变化,如果可以,返回视图,否则返回拷贝文章来源:https://www.toymoban.com/news/detail-490406.html
仍以上面的y
为例,下面是返回拷贝的情况文章来源地址https://www.toymoban.com/news/detail-490406.html
>>> y
tensor([[0, 3],
[1, 4],
[2, 5]])
>>> y.is_contiguous() # y不连续
False
>>> z = y.reshape(2, 3) # 返回拷贝
>>> z
tensor([[0, 3, 1],
[4, 2, 5]])
>>> z.is_contiguous() # z连续
True
>>> y.stride() # y不连续
(1, 3)
>>> z.stride() # z连续
(3, 1)
到了这里,关于【PyTorch】关于张量的连续性(contiguous)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!