Best way to convolve on different channels with single kernel - revisited

krliczki: <p>Hi,<br>
I tried to utilize the following topic:</p><aside class="quote" data-post="2" data-topic="16501">
  <div class="title">
    <div class="quote-controls"></div>
    <img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/ptrblck/48/1823_2.png" class="avatar">
    <a href="https://discuss.pytorch.org/t/best-way-to-convolve-on-different-channels-with-a-single-kernel/16501/2">Best way to convolve on different channels with a single kernel?</a> <a class="badge-category__wrapper " href="/c/autograd/7"><span data-category-id="7" data-drop-close="true" class="badge-category " title="A category of posts relating to the autograd engine itself."><span class="badge-category__name">autograd</span></span></a>
  </div>
  <blockquote>
    You could repeat the single kernel and use the functional API: 
x = Variable(torch.randn(1, in_channels, 100))

# Gaussian kernel
kernel = Variable(torch.FloatTensor([[[0.06136, 0.24477, 0.38774, 0.24477, 0.06136]]]))
weights = kernel.repeat(1, in_channels, 1)
output = F.conv1d(x, weights)

Would this work for your use case?
  </blockquote>
</aside>

<p>what I tried is:</p>
<pre><code class="lang-auto">kernel = np.ones((1, 3, 1))
padding_value = math.floor(kernel.shape[1]/2.)
torch_kernel = torch.Tensor(kernel).permute(0, 2, 1)
data = [[[1., 1.], [2., 2.], [3., 3.], [4., 4.], [5., 5.], [6., 6.], [7., 7.]], [[1., 1.], [2., 2.], [3., 3.], [4., 4.], [5., 5.], [6., 6.], [7., 7.]]]
torch_data = torch.Tensor(data).permute(0, 2, 1)
data_reshaped = torch_data.reshape(-1, 1, torch_data.shape[2])
conv_out = (F.conv1d(data_reshaped, torch_kernel, padding=padding_value, bias=None) / torch_kernel.shape[2]).view(torch_data.shape[0], torch_data.shape[2], torch_data.shape[1])
</code></pre>
<p><code>conv_out</code> is the following:</p>
<pre><code class="lang-auto">tensor([[[1.0000, 2.0000],
         [3.0000, 4.0000],
         [5.0000, 6.0000],
         [4.3333, 1.0000],
         [2.0000, 3.0000],
         [4.0000, 5.0000],
         [6.0000, 4.3333]],

        [[1.0000, 2.0000],
         [3.0000, 4.0000],
         [5.0000, 6.0000],
         [4.3333, 1.0000],
         [2.0000, 3.0000],
         [4.0000, 5.0000],
         [6.0000, 4.3333]]])
</code></pre>
<p>What I would like to see instead is:</p>
<pre><code class="lang-auto">tensor([[[1.0000, 1.0000],
         [2.0000, 2.0000],
         [3.0000, 3.0000],
         [4.0000, 4.0000],
         [5.0000, 5.0000],
         [6.0000, 6.0000],
         [4.3333, 4.3333]],

        [[1.0000, 1.0000],
         [2.0000, 2.0000],
         [3.0000, 3.0000],
         [4.0000, 4.0000],
         [5.0000, 5.0000],
         [6.0000, 6.0000],
         [4.3333, 4.3333]]])
</code></pre>
<p>I am basically trying to do a convolution for a multiple series with fixed kernel for each series. If I unpack one dimension into batches, then I need multi-channel kernel, which doesn’t do the same thing. Could you please help me achieve the desired form of this operation? Maybe this approach my choice of approach is entirely wrong?</p>

ptrblck: <p>You could permute the result tensor as seen here:</p>
<pre><code class="lang-python">conv_out = (F.conv1d(data_reshaped, torch_kernel, padding=padding_value, bias=None) / torch_kernel.shape[2])
ret = conv_out.view(torch_data.shape).permute(0, 2, 1)
print(ret)
&gt; tensor([[[1.0000, 1.0000],
           [2.0000, 2.0000],
           [3.0000, 3.0000],
           [4.0000, 4.0000],
           [5.0000, 5.0000],
           [6.0000, 6.0000],
           [4.3333, 4.3333]],

          [[1.0000, 1.0000],
           [2.0000, 2.0000],
           [3.0000, 3.0000],
           [4.0000, 4.0000],
           [5.0000, 5.0000],
           [6.0000, 6.0000],
           [4.3333, 4.3333]]])
</code></pre>
<p>and you could also use a grouped conv approach:</p>
<pre><code class="lang-python">out = F.conv1d(torch_data, torch_kernel.expand(2, -1, -1), padding=padding_value, bias=None, groups=2) / torch_kernel.shape[2]
out = out.permute(0, 2, 1)
print(out)
</code></pre>