How to convolve along a single axis?

ScientiaEtVeritas: <p>I have two tensors, <code>B</code> and a predefined <code>kernel</code>.</p>
<pre><code class="lang-auto">B.size()
&gt;&gt; torch.Size([6, 6, 1])

kernel.size()
&gt;&gt; torch.Size([5])
</code></pre>
<p>In scipy it’s possible to convolve the tensor with the kernel along a single axis like:</p>
<p><code>convolve1d(B.numpy(),kernel.numpy(), axis=0,mode="constant")</code></p>
<p><code>mode="constant"</code> refers to zero-padding.</p>
<p><code>torch.nn.functional.conv1d</code>, however, doesn’t have a parameter to convolve along a single axis. Is it possible to mimic that behaviour of scipy?</p>
<p>Thank you in advance!</p>

ptrblck: <p><code>nn.Conv1d</code> will use dim2 as the time axis and convolve (or rather cross-correlate) in this dimension.<br>
Therefore, you would need to permute the dimensions in your input.<br>
Here is a small example:</p>
<pre><code class="lang-python">conv = nn.Conv1d(6, 1, kernel_size=5, padding=2)
input = torch.randn(6, 6, 1)
input = input.permute(2, 1, 0)
print(input.shape) # [batch_size, channels, seq]
&gt; torch.Size([1, 6, 6])
output = conv(input)
</code></pre>

ScientiaEtVeritas: <p>But the <code>weight</code> tensor then actually has the shape <code>torch.Size([1, 6, 5])</code>, while my kernel is just <code>torch.Size([5])</code>. Do you suggest to assign a repeated sequence of my kernel to the weights, such as</p>
<p><code>conv.weight = torch.nn.Parameter(kernel.repeat(6).view(1,6,5))</code></p>
<p>But also I expect an output of the same shape as the input, but in your example the output is of shape <code>torch.Size([1, 1, 6])</code>, which is different from the input shape <code>torch.Size([1, 6, 6])</code>. Above scipy function doesn’t change the shape.</p>

phan_phan: <p>The scipy function doesn’t change the shape because it uses padding, by default.<br>
There is an optional <em>padding</em> option for <code>torch.nn.Conv1d</code>.</p>
<p>The shape of the <code>weight</code> tensor depends of the number of <code>in_channels</code> and <code>out_channels</code>.<br>
In your example, can you clarify what does the size <code>[6, 6, 1]</code> of your tensor B correspond to ?</p>

ScientiaEtVeritas: <p>It’s actually <code>[sequence_length, batch_size, value]</code>, and I’m trying to convolve the value along the sequence.</p>

phan_phan: <p>So you work in mono-channel.</p>
<p>In this case, try using <code>B.permute(1, 2, 0)</code> to obtain the desired shape:<br>
<code>[batch_size, in_channels, sequence_length]</code> (<a href="https://pytorch.org/docs/stable/nn.functional.html#conv1d" rel="nofollow noopener">see docs</a>).</p>
<p>Then your <code>kernel</code> of size <code>[5]</code> needs to be <code>[out_channel, in_channels, kernel_size]</code>, so it needs a <code>kernel.view(1, 1, -1)</code>.</p>
<p>And to keep the same size, you need a padding of <code>((kernel_size - 1) / 2)</code> pixels.</p>
<p>So for example, <code>torch.nn.functional.conv1d(B.permute(1, 2, 0), kernel.view(1, 1, -1), padding=2)</code></p>

ScientiaEtVeritas: <p>Thank you! <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"> That did work (almost).<br>
The kernel needed to be mirrored to work exactly like expected and like the scipy function.</p>