True deconvolution layer (not transposed convolution)?

mattrobin: <p>I apologize if this has been asked before, but searching for this is a bit difficult with many people using “deconvolution” for the transposed convolution.</p>
<p>Does PyTorch provide a true deconvolution layer? If not, does anyone have pointers on how to make one from the existing modules/tools? Or is there something that prevents true deconvolution layers from easily being created/used? Thank you for your time!</p>

albanD: <p>Hi,</p>
<p>What do you call a true deconvolution layer? The point of the transposed convolution is to invert the convolution layer, isn’t that what you call true deconvolution?</p>

mattrobin: <p>A true deconvolution would be the mathematical inverse of a convolution. The weights of the deconvolution would accept a 1 x 1 x in_channels input, and output a kernel x kernel x out_channels output.</p>
<p>A transposed convolution does not do this. It performs a ordinary convolution with kernel x kernel x in_channels input to 1 x 1 x out_channels output, but with the striding and padding affecting how the input pixels are input to that convolution such that it produces the same shape as though you had performed a true deconvolution.</p>
<p>While the two approaches produce the same output shape, they produce different results and those results are achieved in very different ways.</p>
<p>So for convolution of stride 2, with kernel 3x3, from the input blue to the output green, the convolution would look like this:<br>
<img src="https://discuss.pytorch.org/uploads/default/original/2X/b/b963a643fa2b3bd9e2d49d871f5bf83c3dc117fa.gif" alt="1*BMngs93_rm2_BpJFH2mS0Q" data-base62-sha1="qs1PsHHoq6dd17KmTmT5VuJTZZE" width="294" height="288" class="animated"><br>
The true deconvolution would be the exact reverse operation. With the green now being the input, and the blue being the output.</p>
<p>In contrast, the analogous transposed convolution (with stride 2 and kernel 3x3) would spread out the input pixels and apply a regular convolution as shown below (with the input being the blue and the output being the green):<br>
<img src="https://discuss.pytorch.org/uploads/default/original/2X/b/be78292481e56065190ad57e784f42062842c7fa.gif" alt="1*Lpn4nag_KRMfGkx1k6bV-g" data-base62-sha1="raYa4KyLeaEVqwi31c80V9N0cLU" width="395" height="449" class="animated"></p>

albanD: <p>Hi,</p>
<p>A true deconvolution would be like inverting a Linear layer then?<br>
It would require the operation to be invertible. For a linear, that would be the weight matrix to be definite positive. If your layer reduces the number of dimensions, this is very unlikely.<br>
In general a true deconvolution would not exist for the same reason? Or am I missing something?</p>

ptrblck: <p>In the context of image processing a deconvolution is the inverse of a convolution <code>f = g * h (+ n)</code>, i.e. to determine the unknown function <code>g</code> given <code>h</code> and <code>f</code>, while <code>n</code> represents the nosie. One could try to approach this problem with the Fourier transform, as this would yield <code>G = F / H - N / H</code> . However, this will usually enhance the noise term, as the spectrum of the filter <code>H</code> usually flattens for high frequencies, while the noise term still has a lot of power in these frequencies.</p>
<p>There are some other techniques like <a href="https://en.wikipedia.org/wiki/Wiener_deconvolution">Wiener deconvolution</a> to counter these noise problems.</p>
<p>Let me know, if I understood your use case right or am completely missing the discussion.</p>

Xinyao_Wang: <p>Let me know if I was wrong, I agree with <a class="mention" href="/u/alband">@albanD</a>, how can you invert a convolution operation?<br>
if you have a 2x2 filter with weights w_ij, and input i_ij, the out put would be out_11 = w_11<em>i_11 + w_12</em>i_12+w_21<em>i_21+w_22</em>i_22. How can you calculate i_11~i_22 if you only know out_11 and all filter weights?</p>
<p>I believe in general deep learning frameworks represent convolution operation as matrix multiplication, and that’s why we can use transposed convolution(the transposed matrix multiplication ) as deconvlution.</p>

mattrobin: <p>Sorry, I may have spoken in a misleading way. I am not looking to find the inverse of a specific convolution. I’m looking for a layer which performs the opposite of a convolution layer. That is, a layer which will accept an input of height x width x in_channels, move across each spatial element being accepted as a 1 x 1 x in_channels input, with each of these outputting a kernel x kernel x out_channels patch, and combining those patches to form a final total output. This can of course also be represented as a similar matrix multiplication as the ordinary convolutions. Is there a reason such a layer would not be an option?</p>

wwiiiii: <p><div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/2X/9/9be484672b9238ea0c350a92384206dcc1f7a613.png" data-download-href="https://discuss.pytorch.org/uploads/default/9be484672b9238ea0c350a92384206dcc1f7a613" title="%EC%BA%A1%EC%B2%98"><img src="https://discuss.pytorch.org/uploads/default/optimized/2X/9/9be484672b9238ea0c350a92384206dcc1f7a613_2_682x500.png" alt="%EC%BA%A1%EC%B2%98" data-base62-sha1="mf5BqR9xtQDmVnzvuYHQqcbFwll" width="682" height="500" srcset="https://discuss.pytorch.org/uploads/default/optimized/2X/9/9be484672b9238ea0c350a92384206dcc1f7a613_2_682x500.png, https://discuss.pytorch.org/uploads/default/optimized/2X/9/9be484672b9238ea0c350a92384206dcc1f7a613_2_1023x750.png 1.5x, https://discuss.pytorch.org/uploads/default/original/2X/9/9be484672b9238ea0c350a92384206dcc1f7a613.png 2x" data-dominant-color="E2E2E9"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">%EC%BA%A1%EC%B2%98</span><span class="informations">1126×825 85.9 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><br>
[image from <a href="http://cvml.ajou.ac.kr/wiki/images/8/83/0_Transposed_convolution.pdf" rel="noopener nofollow ugc">http://cvml.ajou.ac.kr/wiki/images/8/83/0_Transposed_convolution.pdf</a>]<br>
Is it the one you are finding?<br>
If it’s the case, we can simulate it simply by using usual convolution with zero padding to its input.<br>
When we denote input as X, kernel as W (with shape 3 X 3), the convolution of X and W as Z,<br>
X[i][j] contribute Z[i][j] with weight W[1][1], Z[i-1][j-1]  with weight W[0][0], …, etc.</p>

mattrobin: <p>You’re right. You can achieve equivalent results using the transposed convolution.</p>
<p>Interestingly, the image you provided illustrates the transposed convolution using deconvolutions instead of how the transposed convolution actually operates (with the kernel size being applied to the input, not the output). The effect is the same, but the actual process is different. To me, that deconvolution point of view makes more sense (and I assume it makes more sense to others as well, since that’s how they’re illustrating it in their explanation). And further, I think it would require less calculations (since you’re not constantly inputting a bunch of padding zeros into your convolutions). Is there a reason why the implementation is performed this way rather than as a deconvolution?</p>
<p>That is, with the transposed convolution, you’re moving the kernel over the input. If the striding is the same as the kernel size, then for each kernel x kernel size patch of output, you are only using one spatial input element. However, you need to perform the convolution for this one spatial input element kernel x kernel times. That is, placing that element at each possible position in the convolution to get the kernel x kernel outputs. However, if it was performed as a deconvolution, it would be a single deconvolution. You would have the same number of weights but no padding would be used in the deconvolution and so all the calculations would be done at once. Is there some reason this option isn’t available or isn’t more efficient? Am I missing something else?</p>

Zhu_Liu: <p>Hi, <a href="https://arxiv.org/abs/1603.07285" rel="nofollow noopener">the paper</a> (P17) said “Doing so is inefficient and real-world implementations avoid useless multiplications by zero, but conceptionally it is how the transpose of a strided convolution can be thought of”.</p>

zisisnotzis: <p>There is a difference between these two methods, because when we “merge” deconvolution results of all pixels, there can be max, mean (neglecting zero), sum and etc.</p>
<p>But transposed convolution method is only equivalent to sum, which might not be desirable since the number of pixel contributing to a result pixel is changing, which will lead to a “non-uniform” result.</p>

Codezigineer: <p>Can’t you just divide in the frequency domain?</p>