Contiguous()到底怎么用,什么时候用

contiguous原意:邻近的,一个tensor是.is_contiguous() is True,说明该数组按照行展开和底层元数据的存储顺序是一致的

Tensor多维数据的存储,是以多维数组按照行展开成一维数组,作为元数据,原信息里保存了他的形状。调用数据的时候,是按照 stride 取数据的。比如一个三行五列的Tensor,他的stride就是[5,1]。指的是取该维度下一个数据时,要走的步长。

如果要访问矩阵中的下一个元素都是通过偏移来实现,这个偏移量称为步长(stride[1])

为什么需要contiguous?

当我们调用.view()时,如果该数组之前被.permute()或.transpose()过,虽然这两个操作不会改变数组的元数据,但是会新建一个Tensor元信息,该元信息里声明了stride,就导致后续调用.view()时理想的情况是按照transpose后的tensor进行view展开,但实际上会按照底层元数据进行变形。view 仅在底层数组上使用指定的形状进行变形。而且上述直接调用会报错:

view size is not compatible with input tensor's size and stride

Contiguous如何作用的?

t2 = t.transpose(0,1)
t3 = t2.contiguous()

相当于重新开辟了一块内存,t3的元数据是按照变化后的行展开存储的。这样的话,.view()访问底层数组时,就不会产生元信息stride和元数据对应不上的问题了,也不会报错了。

什么时候需要Contiguous?

情况一:

当后续操作改变了元数据,但实际上不想改变原始Tensor的话,需要深拷贝或contiguous,新建内存存储新tensor。如:

x = torch.randn(3, 2)
y = torch.transpose(x, 0, 1)
print("修改前:")
print("x-", x)
print("y-", y)
 
print("\n修改后:")
y[0, 0] = 11
print("x-", x)
print("y-", y)

运行结果:

修改前:
x- tensor([[-0.5670, -1.0277],
           [ 0.1981, -1.2250],
           [ 0.8494, -1.4234]])
y- tensor([[-0.5670,  0.1981,  0.8494],
           [-1.0277, -1.2250, -1.4234]])
 
修改后:
x- tensor([[11.0000, -1.0277],
           [ 0.1981, -1.2250],
           [ 0.8494, -1.4234]])
y- tensor([[11.0000,  0.1981,  0.8494],
           [-1.0277, -1.2250, -1.4234]])

如果对y使用了.contiguous(),改变y的值时,x不会有任何影响!

情况二:

后续需要使用读取元数据的方法,如.view(),仅在底层数组上使用指定的形状进行变形,这时候如果前面使用了transpose、permute等改变元信息但不改变元数据的函数的话,就会出现元信息stride和实际形状不对应,view报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值