Convolution by group of channel

ChiTseHuang: <p>In my work, I need to split filter and input feature map by 4 along channel depth and do convolution individualy.<br>
I want to ask how can I do to facilitate this procedure( maybe can get rid of  “for loop”)<br>
I have tried</p>
<ol>
<li>depth-wise convolution, but I can not reshape weight to correct order to ouput correct result.</li>
<li>torch.multiprocessing, but it seems to be applicable only on those tensor without gradient?</li>
</ol>
<p>My question is how to get every temp_output faster~thanks<br>
code like this</p>
<pre><code class="lang-python">def forward(self, input, weight, padding = 0, stride = 1):
        number = 4
        number_group = int(weight.size(1)/number)
        temp_output_group = [None]*number_group
        for i in range():
            channel_start = i*number
            channel_end = (i+1)*number
            temp_output = F.conv2d(input[:,channel_start:channel_end], weight[:,channel_start:channel_end], padding=padding, stride=stride)
            temp_output_group.append(temp_output)
        #do something with temp_output group
        return ...
</code></pre>

InnovArul: <p>Can you take a look at <code>groups</code> param in <code>F.conv2d()</code> and see if it will help your scenario?<br>
Probably, you could call <code>F.conv2d(input, weight, padding=padding, stride=stride, groups=4)</code>?</p>

ChiTseHuang: <p>Thanks for your reply.<br>
I have tried groups parameter, it’s a good direction.<br>
But it cannot give me the correct output, because reshape weight cannot give the correct weight order for this scenario.<br>
Maybe I need to redefine a reshape function to support.</p>

InnovArul: <p>Would you be able to provide a small script to know how you verified it?</p>

ChiTseHuang: <pre><code class="lang-python">import torch
from torch import nn
import torch.nn.functional as F
input = torch.ones((2,4,2,2))
weight = torch.ones((2,4,2,2))
input[0][1] = input[0][1]*2
input[1][0] = input[1][0]*3
input[1][1] = input[1][1]*4
weight[0][1] = weight[0][1]*2
weight[1][0] = weight[1][0]*3
weight[1][1] = weight[1][1]*4
weight = weight.reshape((4,1,2,2)) 
result = F.conv2d(input, weight, padding=1, stride=1, groups=2)
print(input)
print(weight)
print(result)
print(result.shape)
</code></pre>
<p>I just write this to verify that the number multiplied is not what I want.<br>
Because reshape is to make every channel and still reserve the order of filter<br>
But I need reshape it with the same channel depth in the sub-group<br>
Sorry, maybe I cannot explained it clearly.</p>

InnovArul: <p>Pl. refer to documentation of <a href="https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html">conv2d</a>’s <code>groups</code> parameter here.<br>
According to this, <code>weight</code> parameter shall have the dimension of <code>out_channels  x (in_channels / groups) x h x w</code>.</p>
<p>In your example above,</p>
<p><code>input size = 2 x 4 x 2 x 2</code> (in_channels = 4)<br>
<code>weight size = 2 x 4 x 2 x 2</code> (<code>out_channels</code> = 2, <code>in_channels / groups</code> = 4)</p>
<p>When <code>in_channels=4</code>, <code>groups=2</code>, <code>weight</code> should have size of <code>out_channels x 2 x h x w</code> (i.e., <code>in_channels / groups = 4 / 2 = 2</code>).</p>
<pre><code class="lang-auto">import torch
from torch import nn
import torch.nn.functional as F

input = torch.ones((2,4,2,2))
weight = torch.ones((2,2,2,2))

input[0][1] = input[0][1]*2
input[1][0] = input[1][0]*3
input[1][1] = input[1][1]*4

weight[0][1] = weight[0][1]*2
weight[1][0] = weight[1][0]*3
weight[1][1] = weight[1][1]*4

result = F.conv2d(input, weight, padding=1, stride=1, groups=2)

print(input)
print(weight)
print(result)
print(result.shape)
</code></pre>

ChiTseHuang: <pre><code class="lang-python">import torch
from torch import nn
import torch.nn.functional as F
input = torch.ones((2,4,2,2))
weight = torch.ones((2,4,2,2))
input[0][1] = input[0][1]*2
input[1][0] = input[1][0]*3
input[1][1] = input[1][1]*4
weight[0][1] = weight[0][1]*2
weight[1][0] = weight[1][0]*3
weight[1][1] = weight[1][1]*4
weight = weight.reshape((4,2,2,2))  # this
result = F.conv2d(input, weight, padding=1, stride=1, groups=2)
print(input)
print(weight)
print(result)
print(result.shape)
</code></pre>
<p>Sorry for that I write the code wrongly.<br>
I mean it can work but can not output the result desired for me.<br>
Because reshape the weights, those weights reshaped are not in the order that I need in this scenario.</p>

InnovArul: <p>I am not sure whats the expected output is, in your case.<br>
Either way, If you want to take advantage of parallelization from <code>F.conv2d</code>, you just have to organize your weights accordingly (with appropriate reshape), I guess.</p>

ChiTseHuang: <p>Thanks for your patient responses.</p>