将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
那么,最好使用内置而不是变通方法。