What is Unfold actually doing? so confused!

BarCodeReader: <p>for example, in below code:</p>
<pre><code class="lang-auto">x = torch.arange(50).view((1,1,5,5)).float()
</code></pre>
<p>I will have a tensor like below:</p>
<pre><code class="lang-auto">tensor([[[[ 0.,  1.,  2.,  3.,  4.],
          [ 5.,  6.,  7.,  8.,  9.],
          [10., 11., 12., 13., 14.],
          [15., 16., 17., 18., 19.],
          [20., 21., 22., 23., 24.]]]])
</code></pre>
<p>and from official document:</p>
<pre><code class="lang-auto">torch.nn.Unfold(kernel_size, dilation=1, padding=0, stride=1)
</code></pre>
<blockquote>
<p>: Extracts sliding local blocks from a batched input tensor.</p>
</blockquote>
<p>so if I want a kernel of [3,3] sliding through my tensor with zero-padding 1, I would expect some output like this:</p>
<pre><code class="lang-auto">unfold = nn.Unfold(kernel_size=3, padding=1)
output = unfold(x)

#should gives
# tensor([[[ 0.,  0.,  0.,  0.,  0.,  1.,  0.,  5.,  6.],...]]]
</code></pre>
<p>make sense right? I apply a 3x3 kernel at the padded tensor, flatten it.<br>
but actually, I need to use</p>
<pre><code class="lang-auto">unfold = nn.Unfold(kernel_size=5, padding=1)
output = unfold(x)
</code></pre>
<p><strong>I need to set the kernel size to 5 instead of 3!</strong><br>
Just an comparision:</p>
<pre><code class="lang-auto">unfold = nn.Unfold(kernel_size=3, padding=1)
output = unfold(x)
tensor([[[ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  2.,  3.,  0.,  5.,  6.,  7.,
           8.,  0., 10., 11., 12., 13.,  0., 15., 16., 17., 18.],
         [ 0.,  0.,  0.,  0.,  0.,  0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,
           9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19.],
         [ 0.,  0.,  0.,  0.,  0.,  1.,  2.,  3.,  4.,  0.,  6.,  7.,  8.,  9.,
           0., 11., 12., 13., 14.,  0., 16., 17., 18., 19.,  0.],
         [ 0.,  0.,  1.,  2.,  3.,  0.,  5.,  6.,  7.,  8.,  0., 10., 11., 12.,
          13.,  0., 15., 16., 17., 18.,  0., 20., 21., 22., 23.],
         [ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12., 13.,
          14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.],
         [ 1.,  2.,  3.,  4.,  0.,  6.,  7.,  8.,  9.,  0., 11., 12., 13., 14.,
           0., 16., 17., 18., 19.,  0., 21., 22., 23., 24.,  0.],
         [ 0.,  5.,  6.,  7.,  8.,  0., 10., 11., 12., 13.,  0., 15., 16., 17.,
          18.,  0., 20., 21., 22., 23.,  0.,  0.,  0.,  0.,  0.],
         [ 5.,  6.,  7.,  8.,  9., 10., 11., 12., 13., 14., 15., 16., 17., 18.,
          19., 20., 21., 22., 23., 24.,  0.,  0.,  0.,  0.,  0.],
         [ 6.,  7.,  8.,  9.,  0., 11., 12., 13., 14.,  0., 16., 17., 18., 19.,
           0., 21., 22., 23., 24.,  0.,  0.,  0.,  0.,  0.,  0.]]])

unfold = nn.Unfold(kernel_size=5, padding=1)
output = unfold(x)
tensor([[[ 0.,  0.,  0.,  0.,  0.,  1.,  0.,  5.,  6.],
         [ 0.,  0.,  0.,  0.,  1.,  2.,  5.,  6.,  7.],
         [ 0.,  0.,  0.,  1.,  2.,  3.,  6.,  7.,  8.],
         [ 0.,  0.,  0.,  2.,  3.,  4.,  7.,  8.,  9.],
         [ 0.,  0.,  0.,  3.,  4.,  0.,  8.,  9.,  0.],
         [ 0.,  0.,  1.,  0.,  5.,  6.,  0., 10., 11.],
         [ 0.,  1.,  2.,  5.,  6.,  7., 10., 11., 12.],
         [ 1.,  2.,  3.,  6.,  7.,  8., 11., 12., 13.],
         [ 2.,  3.,  4.,  7.,  8.,  9., 12., 13., 14.],
         [ 3.,  4.,  0.,  8.,  9.,  0., 13., 14.,  0.],
         [ 0.,  5.,  6.,  0., 10., 11.,  0., 15., 16.],
         [ 5.,  6.,  7., 10., 11., 12., 15., 16., 17.],
         [ 6.,  7.,  8., 11., 12., 13., 16., 17., 18.],
         [ 7.,  8.,  9., 12., 13., 14., 17., 18., 19.],
         [ 8.,  9.,  0., 13., 14.,  0., 18., 19.,  0.],
         [ 0., 10., 11.,  0., 15., 16.,  0., 20., 21.],
         [10., 11., 12., 15., 16., 17., 20., 21., 22.],
         [11., 12., 13., 16., 17., 18., 21., 22., 23.],
         [12., 13., 14., 17., 18., 19., 22., 23., 24.],
         [13., 14.,  0., 18., 19.,  0., 23., 24.,  0.],
         [ 0., 15., 16.,  0., 20., 21.,  0.,  0.,  0.],
         [15., 16., 17., 20., 21., 22.,  0.,  0.,  0.],
         [16., 17., 18., 21., 22., 23.,  0.,  0.,  0.],
         [17., 18., 19., 22., 23., 24.,  0.,  0.,  0.],
         [18., 19.,  0., 23., 24.,  0.,  0.,  0.,  0.]]])
</code></pre>

BarCodeReader: <p>also when we change the value of stride, the value returned is not what I expected…</p>
<p><strong>@ <a href="https://discuss.pytorch.org/u/ptrblck">ptrblck</a></strong> need your help and please take a look into this issue…Really appreciate!</p>

ptrblck: <p>The output shape is described in the <a href="https://pytorch.org/docs/stable/nn.html?highlight=unfo%20ld#torch.nn.Unfold">docs</a> and explains that dim1 will hold the window values.</p>
<p>In your use case</p>
<pre><code class="lang-python">print(output[0, :, 0])
&gt; tensor([0., 0., 0., 0., 0., 1., 0., 5., 6.])
</code></pre>
<p>will print the expected result.</p>

BarCodeReader: <p>what I really confuse is I need to set the kernel size to 5 instead of 3 to get above result:</p>
<pre><code class="lang-auto">unfold = nn.Unfold(kernel_size=5, padding=1)
</code></pre>
<p>for an input tensor like below, why the kernel size is 5, I don’t really understand</p>
<pre><code class="lang-auto">tensor([[[[ 0.,  1.,  2.,  3.,  4.],
          [ 5.,  6.,  7.,  8.,  9.],
          [10., 11., 12., 13., 14.],
          [15., 16., 17., 18., 19.],
          [20., 21., 22., 23., 24.]]]])
</code></pre>

ptrblck: <p>For a kernel size of 5, you’ll get the expected output:</p>
<pre><code class="lang-python">print(output[0, :, 0])
&gt; tensor([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  2.,  3.,  0.,  5.,  6.,  7.,
         8.,  0., 10., 11., 12., 13.,  0., 15., 16., 17., 18.])
</code></pre>
<p>You are looking at the wrong dimension, since your input is also <code>5x5</code> in the spatial size.</p>

BarCodeReader: <p>my bad…I think i really have some misunderstanding with the document.<br>
now after I follow your approach, it works fine.</p>
<p>Thanks for your help!</p>