Converting tensorflow model to pytorch: issue with padding

hugh: <p>I was re-writing a model in pytorch from tensorflow and came across of issues with padding. In the tensorflow model, the padding used in “SAME” and I tried to replicate that according to this:<img src="https://discuss.pytorch.org/uploads/default/original/3X/f/b/fb37ef4485f0bc58bb415b54943764f92eaa3bbf.png" alt="pad" data-base62-sha1="zQnGrcgWzuvutP3kTKFJQT4IHYb" width="619" height="127"></p>
<p>After loading the tensorflow weights in, everything looks good until I hit the layers with “SAME” padding. I’ve read some previous post where others have had some trouble with replicating “SAME” padding in pytorch, but I haven’t come across posts where this was a problem when converting a tensorflow model to a pytorch model. The documentation on how “SAME” padding is calculated also didn’t seem to be very detailed (but maybe I’m looking at the wrong place).</p>
<p>For more info on the convolution layer, it is<br>
in_channel = 526<br>
out_channel = 64<br>
input_shape = 140x140<br>
kernel_size = 3x3<br>
dilation = 1<br>
stride = 2</p>
<p>Any advice or suggestions here would greatly help!</p>

Nikronic: <p>Hi,</p>
<p>PyTorch does not support <code>same</code> padding explicitly, but you can obviously find the proper padding size <code>p</code> using the exact same formula you have provided. In your case, something especial is that padding size cannot be an integer number which means you have to have one side more padded.</p>
<pre><code class="lang-auto">(2*(output-1) - input - kernel)*(1 / stride)
</code></pre>
<p>Will give you 70.5 as the proper padding size. So, symmetric padding is not possible but for asymmetric case you can achieve it using <code>torch.nn.functional.pad(input, (int, int, int, int))</code> for `left, right, top and bottom respectively.<br>
Here is an example with your values:</p>
<pre><code class="lang-auto">x = torch.randn(1, 526, 140, 140)
x = F.pad(x, (71, 70, 71, 70), )
x = nn.Conv2d(526, 64, 3, 2)(x)
x.shape
</code></pre>
<p>Bests</p>

FatherShawn: <p>A note for anyone else who might go looking for the source of the formula referenced by the O.P.  It is from <a href="https://arxiv.org/pdf/1603.07285.pdf" rel="noopener nofollow ugc">A guide to convolution arithmetic for deep learning</a> with accompanying repository at <a href="https://github.com/vdumoulin/conv_arithmetic" rel="noopener nofollow ugc">https://github.com/vdumoulin/conv_arithmetic</a></p>

agudmundson: <p>Hello,</p>
<p>Perhaps, there is a typo in <a class="mention" href="/u/nikronic">@Nikronic</a> equation above. The correct padding is shown in the code, but the equation doesn’t produce the same answer. So, just in case someone revisits this thread in the future and is confused, I believe it was meant to be:</p>
<blockquote>
<p>pad = [ (stride * (output-1))  - input  +  kernel ] / 2</p>
</blockquote>
<p>Following the formula <a class="mention" href="/u/hugh">@hugh</a> posted above:</p>
<blockquote>
<p>output  <em><strong>=</strong></em> [ (input  +  (2 * pad) - kernel)  /  stride ]  +  1<br>
output  -  1  <em><strong>=</strong></em> (input  +  (2 * pad) - kernel)  /  stride<br>
(stride  *  (output  -  1))  <em><strong>=</strong></em>  input  +  (2 * pad)  -  kernel<br>
(stride  *  (output  -  1)) - input + kernel <em><strong>=</strong></em>  2 * pad<br>
[(stride  *  (output  -  1)) - input + kernel]  /  2 <em><strong>=</strong></em> pad</p>
</blockquote>
<p>or in code:<br>
<code>pad = lambda input, output, kernel, stride:  (  ( (stride * (output - 1) )   -  input  +  kernel  )  /  2</code><br>
Thank you all and happy coding!</p>