Efficient pseudo-inverse for PyTorch 2D convolution

111414: <p><strong>Background:</strong></p>
<p>Thanks for your attention! I am learning the basic knowledge of 2D convolution, linear algebra and PyTorch. I encounter the implementation problem about the psedo-inverse of the convolution operator. Specifically, I have no idea about how to implement it in an efficient way. Please see the following problem statements for details. Any help/tip/suggestion is welcomed.</p>
<p>(Thanks a lot for your attention!)</p>
<hr>
<p><strong>The Original Problem:</strong></p>
<p>I have an image feature <code>x</code> with shape <code>[b,c,h,w]</code> and a <code>3x3</code> convolutional kernel <code>K</code> with shape <code>[c,c,3,3]</code>. There is <code>y = K * x</code>. How to implement the corresponding pseudo-inverse on <code>y</code> in an efficient way?</p>
<blockquote>
<p>There is [y = K * x = Ax], how to implement [x_hat = (A^+)y]?</p>
</blockquote>
<p>I guess that there should be some operations using <code>torch.fft</code>. However, I still have no idea about how to implement it. I do not know if there exists an implementation previously.</p>
<pre data-code-wrap="python"><code class="lang-python">import torch
import torch.nn.functional as F

c = 32
K = torch.randn(c, c, 3, 3)
x = torch.randn(1, c, 128, 128)
y = F.conv2d(x, K, padding=1)

print(y.shape)

# How to implement pseudo-inverse for y = K * x in an efficient way?
</code></pre>
<hr>
<p><strong>Some of My Efforts:</strong></p>
<p>I may know that the 2D convolution is a linear operator. It is equivalent to a “matrix product” operator. We can actually write out the matrix form of the convolution and calculate its psedo-inverse. However, I think this type of operation will be inefficient. And I have no idea about how to implement it in an efficient way.</p>
<p>According to <a href="https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_inverse" rel="noopener nofollow ugc">Wikipedia</a>, the psedo-inverse may satisfy the property of <code>A(A_pinv(x))=x</code>, where <code>A</code> is the convolutional operator, <code>A_pinv</code> is its psedo-inverse, and <code>x</code> may be any image feature.</p>
<p>(Thanks again for reading such a long post!)</p>

tom: <p>The thing here is that the inverse of a sparse matrix (like convolution) is not, in general, sparse / similar in structure, so if you were to derive the inverse by looking at the matrix and inverting that, you would not get a proper inverse.</p>
<aside class="onebox stackexchange" data-onebox-src="https://stackoverflow.com/questions/2080835/deriving-the-inverse-filter-of-image-convolution-kernel">
  <header class="source">

      <a href="https://stackoverflow.com/questions/2080835/deriving-the-inverse-filter-of-image-convolution-kernel" target="_blank" rel="noopener nofollow ugc">stackoverflow.com</a>
  </header>

  <article class="onebox-body">
      <a href="https://stackoverflow.com/users/195787/royi" target="_blank" rel="noopener nofollow ugc">
    <img alt="Royi" src="https://www.gravatar.com/avatar/4b9620cb172292493f9c02c8f37c6cc7?s=256&amp;d=identicon&amp;r=PG" class="thumbnail onebox-avatar" width="256" height="256">
  </a>

<h4>
  <a href="https://stackoverflow.com/questions/2080835/deriving-the-inverse-filter-of-image-convolution-kernel" target="_blank" rel="noopener nofollow ugc">Deriving the Inverse Filter of Image Convolution Kernel</a>
</h4>

<div class="tags">
  <strong>image-processing, filter, signal-processing</strong>
</div>

<div class="date">
  asked by
  
  <a href="https://stackoverflow.com/users/195787/royi" target="_blank" rel="noopener nofollow ugc">
    Royi
  </a>
  on <a href="https://stackoverflow.com/questions/2080835/deriving-the-inverse-filter-of-image-convolution-kernel" target="_blank" rel="noopener nofollow ugc">11:43AM - 17 Jan 10 UTC</a>
</div>

  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>


111414: <p>Thank you so much, <a class="mention" href="/u/tom">@tom</a> ! <img src="https://discuss.pytorch.org/images/emoji/apple/smile.png?v=12" title=":smile:" class="emoji" alt=":smile:" loading="lazy" width="20" height="20"> I read your provided reference. It seems that the Wiener filtering is useful for me. Is there a way to efficiently implement it by PyTorch for a <code>[b,c,h,w]</code> feature and a <code>[c,c,k,k]</code> convolutional kernel? <img src="https://discuss.pytorch.org/images/emoji/apple/thinking.png?v=12" title=":thinking:" class="emoji" alt=":thinking:" loading="lazy" width="20" height="20"></p>

fengxinmin: <p>Hi Bin, have you solved this problem? If so, could you please share your approach? I also encountered similar problems.</p>