Pytorch 关于张量部分的看法

Pytorch 关于张量部分的看法,pytorch,Pytorch,我有一个多维张量,让我们以这个简单的张量为例: out = torch.Tensor(3, 4, 5) 我必须得到这个张量的一部分/子部分[:,0,:],然后应用方法视图(-1),但这是不可能的: out[:,0,:].view(-1) RuntimeError:无效参数2:视图大小与输入张量的大小和跨距不兼容(至少有一个维度跨越两个相邻的子空间)。在.view()之前调用.continuous()。在../aten/src/TH/generic/THTensor.cpp:203 解决方案

我有一个多维张量,让我们以这个简单的张量为例:

out = torch.Tensor(3, 4, 5)
我必须得到这个张量
的一部分/子部分[:,0,:]
,然后应用方法
视图(-1)
,但这是不可能的:

 out[:,0,:].view(-1)
RuntimeError:无效参数2:视图大小与输入张量的大小和跨距不兼容(至少有一个维度跨越两个相邻的子空间)。在.view()之前调用.continuous()。在../aten/src/TH/generic/THTensor.cpp:203

解决方案是克隆子部分:

 out[:,0,:].clone().view(-1)

有比克隆更好/更快的解决方案吗?

您所做的一切都会很好。也就是说,一种更具可移植性的方法是使用它,它将在可能时返回一个视图,但在必要时将创建一个连续副本。这样,它将以最快的速度完成任务。在您的情况下,必须复制数据,但如果始终使用
重塑
,则会出现无法生成副本的情况

所以你可以用

out[:,0,:].reshape(-1)

明白了

这里有一个重要的问题。如果对
重塑
的输出执行就地操作,则这可能会影响原始张量,也可能不会影响原始张量,具体取决于是否返回了视图或副本

例如,假设
out
已经是连续的,那么在本例中

>>> x = out[:,0,:].reshape(-1)    # returns a copy
>>> x[0] = 10
>>> print(out[0,0,0].item() == 10)
False
>>> x = out[:,:,0].reshape(-1)     # returns a view
>>> x[0] = 10
>>> print(out[0,0,0].item() == 10)
True
x
是一个副本,因此对它的更改不会影响
out
。但在这种情况下

>>> x = out[:,0,:].reshape(-1)    # returns a copy
>>> x[0] = 10
>>> print(out[0,0,0].item() == 10)
False
>>> x = out[:,:,0].reshape(-1)     # returns a view
>>> x[0] = 10
>>> print(out[0,0,0].item() == 10)
True
x
是一个视图,因此对
x
的就地更改也将更改
out


备选方案

两种选择是

out[:,0,:].flatten()    # .flatten is just a special case of .reshape

虽然如果您想要最快的方法,我建议您使用
continuous().view
来反对后一种方法,因为通常情况下,它比
重塑
展平
更可能返回副本。这是因为即使基础数据在后续条目之间具有相同的字节数,
continuous
也会创建一个副本。因此,两者之间是有区别的

out[:,:,0].contiguous().view(-1)       # creates a copy

其中,
continuous().view
方法强制复制,因为
out[:,:,0]
不是连续的,但是
展平
/
重塑
将创建一个视图,因为基础数据是均匀间隔的

例如,有时
continuous()
不会创建副本

out[0,:,:].contiguous().view(-1)       # creates a view b/c out[0,:,:] already is contiguous

因为
out[0,:,::]
已经是连续的,所以它们都可以在不复制的情况下生成原始数据的视图



如果您想确保
输出
与其扁平化的对应项完全解耦,那么使用
.clone()
的原始方法就是一个不错的选择。

非常感谢您给出了这个完整的答案。此代码在调用多个丢失函数之前使用。事实上,我这样做是为了隔离每个输出,然后将它们传递给适当的损失函数。这些函数都不能修改张量,所以我应该没问题。
out[0,:,:].flatten()                   # creates a view