将pytorch张量切割成重叠块的最佳方法?
例如,如果我有:将pytorch张量切割成重叠块的最佳方法?,pytorch,Pytorch,例如,如果我有: eg6 = torch.tensor([ [ 1., 7., 13., 19.], [ 2., 8., 14., 20.], [ 3., 9., 15., 21.], [ 4., 10., 16., 22.], [ 5., 11., 17., 23.], [ 6., 12., 18., 24.]]) batch1 = eg6 batch2 = -eg6 x = torch.cat((batch1,batch2)).view(
eg6 = torch.tensor([
[ 1., 7., 13., 19.],
[ 2., 8., 14., 20.],
[ 3., 9., 15., 21.],
[ 4., 10., 16., 22.],
[ 5., 11., 17., 23.],
[ 6., 12., 18., 24.]])
batch1 = eg6
batch2 = -eg6
x = torch.cat((batch1,batch2)).view(2,6,4)
然后我想把它分割成重叠的块,像一个滑动窗口函数,并使这些块可以批处理。例如,仅看第一个维度,我想要1,2,3
,3,4,5
,5,6
(或5,6,0
)
这似乎是我想要的。出于某种原因,它转换了最后两个维度,但这很容易修复。将其从形状[2,3,3,4]
更改为[6,3,4]
需要内存副本,但我认为这是不可避免的
SZ=3
x2 = x.unfold(1,SZ,2).transpose(2,3).reshape(-1,SZ,4)
当x
的形状为[2,7,4]
时,此功能非常有效。但是只有6排,它就扔掉了最后一排
是否有一个版本的unfold()
或者在调用unfold()
之前是否需要填充x
?最好的方法是什么?我想知道“pad”是否是一个错误的词,因为我只找到了希望在两端都放置填充字符的函数,并考虑了卷积
旁白:看,奇怪的转置似乎是有意而明确地存在的?!出于这个原因,以及不希望出现的切块行为,这让我认为我的问题的正确答案可能是编写一个新的低级函数。但这对我来说太多了,至少对今天来说。。。(我认为还需要编写向后传递的第二个函数。)此处执行的操作类似于1D卷积。使用kernel\u size=SZ
和stride=2
。正如您所注意到的,如果您没有提供足够的填充(您的措辞是正确的),最后一个元素将不会被使用
一般的方法(对于任何SZ
和任何输入形状x.size(1)
)是确定是否需要填充,如果需要,需要多少填充
- 输出的大小由
out=floor((x.size(1)-SZ)/2+1)
给出
- 未使用元素的数量为
x.size(1)-out*(SZ-1)-1
- 如果未使用元素的数量不为零,则需要添加一个
(out+1)*(SZ-1)+1-x.size(1)
此示例不需要填充:
>>> x = torch.stack((torch.tensor([
[ 1., 7., 13., 19.],
[ 2., 8., 14., 20.],
[ 3., 9., 15., 21.],
[ 4., 10., 16., 22.],
[ 5., 11., 17., 23.]]),)*2)
>>> x.shape
torch.Size([2, 5, 4])
>>> out = floor((x.size(1) - SZ)/2 + 1)
2
>>> unused = x.size(1) - out*(SZ-1) - 1
0
而这一条将:
>>> x = torch.stack((torch.tensor([
[ 1., 7., 13., 19.],
[ 2., 8., 14., 20.],
[ 3., 9., 15., 21.],
[ 4., 10., 16., 22.],
[ 5., 11., 17., 23.],
[ 6., 12., 18., 24.]]),)*2)
>>> x.shape
torch.Size([2, 6, 4])
>>> out = floor((x.size(1) - SZ)/2 + 1)
2
>>> unused = x.size(1) - out*(SZ-1) - 1
1
>>> p = (out+1)*(SZ-1) + 1 - x.size(1)
1
现在,要实际添加填充,您可以使用torch.cat
。虽然我是内置的,但会工作
>>> torch.cat((x, torch.zeros(x.size(0), p, x.size(2))), dim=1)
tensor([[[ 1., 7., 13., 19.],
[ 2., 8., 14., 20.],
[ 3., 9., 15., 21.],
[ 4., 10., 16., 22.],
[ 5., 11., 17., 23.],
[ 6., 12., 18., 24.],
[ 0., 0., 0., 0.]],
[[ 1., 7., 13., 19.],
[ 2., 8., 14., 20.],
[ 3., 9., 15., 21.],
[ 4., 10., 16., 22.],
[ 5., 11., 17., 23.],
[ 6., 12., 18., 24.],
[ 0., 0., 0., 0.]]])
使用F.pad(x,(0,0,0,p))
确实有效,而且比cat
更容易阅读(我猜它至少也同样有效??)。我使用了p=(SZ-overlap)-1
,它给出了所需填充量的上限:当unfold()
扔掉多余部分时,这并不重要。很好,一定要使用F.pad
那么,最好使用内置而不是变通方法。