【问题标题】:How does Pytorch's "Fold" and "Unfold" work?Pytorch 的“折叠”和“展开”是如何工作的?
【发布时间】:2019-05-27 02:00:19
【问题描述】:

我已经通过了official doc。我很难理解这个函数的用途以及它是如何工作的。有人可以用外行的方式解释吗?

尽管我使用的 Pytorch 版本与文档匹配,但他们提供的示例出现错误。也许修复我所做的错误应该教会我一些东西?文档中给出的sn-p是:

   fold = nn.Fold(output_size=(4, 5), kernel_size=(2, 2))
   input = torch.randn(1, 3 * 2 * 2, 1)
   output = fold(input)
   output.size()

而固定的sn-p是:

   fold = nn.Fold(output_size=(4, 5), kernel_size=(2, 2))
   input = torch.randn(1, 3 * 2 * 2, 3 * 2 * 2)
   output = fold(input)
   output.size()

谢谢!

【问题讨论】:

    标签: python machine-learning deep-learning computer-vision pytorch


    【解决方案1】:

    unfoldfold 用于促进“滑动窗口”操作(如卷积)。
    假设您想将函数 foo 应用于特征图/图像中的每个 5x5 窗口:

    from torch.nn import functional as f
    windows = f.unfold(x, kernel_size=5)
    

    现在windowssize的batch-(5*5*x.size(1))-num_windows,你可以在windows上申请foo

    processed = foo(windows)
    

    现在你需要将processed“折叠”回x的原始大小:

    out = f.fold(processed, x.shape[-2:], kernel_size=5)
    

    您需要注意paddingkernel_size,这可能会影响您将processed“折叠”回x 大小的能力。
    此外,fold sums 覆盖重叠的元素,因此您可能希望将 fold 的输出除以补丁大小。

    【讨论】:

      【解决方案2】:

      一维展开很容易:

      x = torch.arange(1, 9).float()
      print(x)
      # dimension, size, step
      print(x.unfold(0, 2, 1))
      print(x.unfold(0, 3, 2))
      

      输出:

      tensor([1., 2., 3., 4., 5., 6., 7., 8.])
      tensor([[1., 2.],
              [2., 3.],
              [3., 4.],
              [4., 5.],
              [5., 6.],
              [6., 7.],
              [7., 8.]])
      tensor([[1., 2., 3.],
              [3., 4., 5.],
              [5., 6., 7.]])
      

      二维展开(也称为修补

      import torch
      patch=(3,3)
      x=torch.arange(16).float()
      print(x, x.shape)
      x2d = x.reshape(1,1,4,4)
      print(x2d, x2d.shape)
      h,w = patch
      c=x2d.size(1)
      print(c) # channels
      # unfold(dimension, size, step)
      r = x2d.unfold(2,h,1).unfold(3,w,1).transpose(1,3).reshape(-1, c, h, w)
      print(r.shape)
      print(r) # result
      
      tensor([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12., 13.,
              14., 15.]) torch.Size([16])
      tensor([[[[ 0.,  1.,  2.,  3.],
                [ 4.,  5.,  6.,  7.],
                [ 8.,  9., 10., 11.],
                [12., 13., 14., 15.]]]]) torch.Size([1, 1, 4, 4])
      1
      torch.Size([4, 1, 3, 3])
      
      tensor([[[[ 0.,  1.,  2.],
                [ 4.,  5.,  6.],
                [ 8.,  9., 10.]]],
      
      
              [[[ 4.,  5.,  6.],
                [ 8.,  9., 10.],
                [12., 13., 14.]]],
      
      
              [[[ 1.,  2.,  3.],
                [ 5.,  6.,  7.],
                [ 9., 10., 11.]]],
      
      
              [[[ 5.,  6.,  7.],
                [ 9., 10., 11.],
                [13., 14., 15.]]]])
      

      【讨论】:

      • 能不能加上对应的.fold操作返回到原来的张量?
      • 查看fold example
      • 通过F.unfold(input=x2d, kernel_size=(3, 3), dilation=(1, 1), stride=(1, 1), padding=(0, 0) 之类的操作,通过单个F.unfold() 调用是否可以获得相同的结果?
      【解决方案3】:

      unfold 将张量想象为更长的张量,其中重复的列/行值“折叠”在彼此之上,然后“展开”:

      • size 确定折叠的大小
      • step 确定折叠的频率

      例如对于 2x5 张量,使用 step=1 展开它,并在 dim=1 上修补 size=2

      x = torch.tensor([[1,2,3,4,5],
                        [6,7,8,9,10]])
      
      >>> x.unfold(1,2,1)
      tensor([[[ 1,  2], [ 2,  3], [ 3,  4], [ 4,  5]],
              [[ 6,  7], [ 7,  8], [ 8,  9], [ 9, 10]]])
      

      fold 与此操作大致相反,但输出中会汇总“重叠”值。

      【讨论】:

      • 你的画为我赚了一分钱!谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-13
      • 2013-06-06
      • 2020-11-09
      • 1970-01-01
      相关资源
      最近更新 更多