nn.Conv3d: papping each input channel to the corresponding output channel without summation with other input channels

arman.avesta: <p>Hi,</p>
<p>I’m doing 3D convolutions on multi-channel MR images. I have equal number of input and output channels, and I want each input channel to be mapped to the corresponding output channel, without being summed with other input channels. I’m planning to use “groups” and I want to make sure it’s the correct strategy.</p>
<p>This block of code sums the input channels, which I don’t want:</p>
<pre><code class="lang-auto">class separateChannelsConv(nn.Module):
    
    def __init__(self, channels, kernel_size=3, stride=1, padding=1):
        super().__init__()
        self.conv = nn.Conv3d(channels, channels, kernel_size, stride, padding)
        
    def forward(self, x):
        return self.conv(x)
</code></pre>
<p>This block of code doesn’t sum the input channels, which is ideal. I just want to make sure that a separate kernel is used to map each input channels to the corresponding output channels (as opposed to one kernel mapping all input channels to the corresponding output channels):</p>
<pre><code class="lang-auto">class separateChannelsConv(nn.Module):

    def __init__(self, channels, kernel_size=3, stride=1, padding=1):
        super().__init__()
        self.conv = nn.Conv3d(channels, channels, kernel_size, stride, padding, groups=channels)

    def forward(self, x):
        return self.conv(x)
</code></pre>
<p>Please confirm that using “groups” is the right strategy to achieve my goal: to map each input channel to the corresponding output channel without summation with other input channels?</p>
<p>Thanks a lot,<br>
Arman</p>

KFrank: <p>Hi Arman!</p>
<aside class="quote no-group quote-modified" data-username="arman.avesta" data-post="1" data-topic="128337" data-full="true">
<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/arman.avesta/48/40219_2.png" class="avatar"> arman.avesta:</div>
<blockquote>
<pre><code class="lang-auto">        self.conv = nn.Conv3d(channels, channels, kernel_size, stride, padding, groups=channels)
</code></pre>
<p>Please confirm that using “groups” is the right strategy to achieve my goal:</p>
</blockquote>
</aside>
<p>Yes, setting <code>groups = channels</code> will do what you want.</p>
<p>Let’s illustrate this with a simple case:</p>
<pre><code class="lang-plaintext">&gt;&gt;&gt; import torch
&gt;&gt;&gt; torch.__version__
'1.9.0'
&gt;&gt;&gt; conv = torch.nn.Conv3d (3, 3, 1, groups = 3, bias = False)
&gt;&gt;&gt; conv.weight[:, :, 0, 0, 0]
tensor([[-0.5339],
        [-0.6689],
        [-0.9413]], grad_fn=&lt;SelectBackward&gt;)
&gt;&gt;&gt; conv (torch.tensor ([1.0, 0.0, 0.0]).reshape (1, 3, 1, 1, 1))
tensor([[[[[-0.5339]]],


         [[[ 0.0000]]],


         [[[ 0.0000]]]]], grad_fn=&lt;MkldnnConvolutionBackward&gt;)
&gt;&gt;&gt; conv (torch.tensor ([0.0, 1.0, 0.0]).reshape (1, 3, 1, 1, 1))
tensor([[[[[ 0.0000]]],


         [[[-0.6689]]],


         [[[ 0.0000]]]]], grad_fn=&lt;MkldnnConvolutionBackward&gt;)
&gt;&gt;&gt; conv (torch.tensor ([0.0, 0.0, 1.0]).reshape (1, 3, 1, 1, 1))
tensor([[[[[ 0.0000]]],


         [[[ 0.0000]]],


         [[[-0.9413]]]]], grad_fn=&lt;MkldnnConvolutionBackward&gt;)
</code></pre>
<p>Best.</p>
<p>K. Frank</p>

arman.avesta: <p>Thank you so much, Frank!</p>