Changing the weights of Conv2d

isalirezag: <p>So I am trying to do filtering via <code>Conv2d</code>, I define my kernel and then change the weights of Conv2d and thought that should be it, but the results does not match</p>
<p>For a toy example, I define a <code>3x3</code> kernel : <code>[[0, 0, 0],[0, 1, 0],[0, 0, 0]]</code>, the output results of using this kernel should basically give me identical results as an input. but I am not sure why it is not happening like that:</p>
<p>Here is the whole toy code:</p>
<pre><code class="lang-auto">import torch
import torchvision
import torchvision.transforms as transforms
import torch.nn as nn
import torch.nn.functional as F
import torch

Input = torch.rand(1,2,6,6)

Guass = nn.Conv2d(Input.size(1), Input.size(1), 3, padding = 1)
KernelGauss = torch.ones(3,3)*0.
KernelGauss[1,1] = 1.
KernelGaussExpand = KernelGauss.expand(Guass.weight.size())
Guass.weight = torch.nn.Parameter(KernelGaussExpand, requires_grad=False)

OutPut = Guass(Input)

print('KernelGauss: {}' .format(KernelGauss))
print('Input: {}' .format(Input))
print('OutPut: {}' .format(OutPut))
</code></pre>
<pre><code class="lang-auto">KernelGauss: tensor([[0., 0., 0.],
        [0., 1., 0.],
        [0., 0., 0.]])
Input: tensor([[[[0.1694, 0.0436, 0.7638, 0.4422, 0.6436, 0.1260],
          [0.2136, 0.2536, 0.1094, 0.6026, 0.2102, 0.8117],
          [0.6218, 0.5365, 0.9977, 0.4297, 0.4261, 0.7260],
          [0.8062, 0.3274, 0.4722, 0.2773, 0.4304, 0.7448],
          [0.6605, 0.8976, 0.7353, 0.7233, 0.9757, 0.2564],
          [0.6651, 0.2333, 0.2524, 0.8768, 0.0754, 0.4961]],

         [[0.8020, 0.6601, 0.4271, 0.3141, 0.6387, 0.8583],
          [0.3664, 0.9589, 0.7841, 0.6330, 0.0851, 0.4114],
          [0.4414, 0.9218, 0.1864, 0.5323, 0.4601, 0.4648],
          [0.0841, 0.8478, 0.8975, 0.1383, 0.0706, 0.0810],
          [0.8904, 0.7208, 0.2150, 0.0034, 0.4385, 0.7455],
          [0.8900, 0.6735, 0.5207, 0.4046, 0.6463, 0.9222]]]])
OutPut: tensor([[[[1.1774, 0.9097, 1.3969, 0.9623, 1.4883, 1.1903],
          [0.7860, 1.4185, 1.0995, 1.4416, 0.5013, 1.4290],
          [1.2692, 1.6643, 1.3901, 1.1680, 1.0922, 1.3967],
          [1.0962, 1.3812, 1.5756, 0.6216, 0.7070, 1.0318],
          [1.7568, 1.8244, 1.1563, 0.9327, 1.6201, 1.2078],
          [1.7611, 1.1128, 0.9791, 1.4874, 0.9277, 1.6242]],

         [[1.0561, 0.7884, 1.2756, 0.8410, 1.3670, 1.0690],
          [0.6647, 1.2972, 0.9782, 1.3203, 0.3800, 1.3077],
          [1.1479, 1.5430, 1.2688, 1.0467, 0.9709, 1.2754],
          [0.9749, 1.2599, 1.4543, 0.5003, 0.5857, 0.9105],
          [1.6355, 1.7031, 1.0349, 0.8114, 1.4988, 1.0865],
          [1.6398, 0.9915, 0.8578, 1.3661, 0.8064, 1.5029]]]],
       grad_fn=&lt;ThnnConv2DBackward&gt;)
</code></pre>

InnovArul: <p>Did you forget about the bias?</p>

justusschock: <p>You forgot to deactivate the bias term (which is True by default)</p>
<p>Edit: <a class="mention" href="/u/innovarul">@InnovArul</a> was a few seconds faster, so nvm <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=5" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

isalirezag: <p>how should i deactivate it?</p>

justusschock: <pre><code class="lang-auto">Guass = nn.Conv2d(Input.size(1), Input.size(1), 3, padding = 1, bias=False)
</code></pre>
<p>Also note your typo in the layers name.</p>

InnovArul: <p><code>nn.Conv2d(Input.size(1), Input.size(1), 3, padding = 1, bias=False)</code></p>
<p><a class="mention" href="/u/justusschock">@justusschock</a> <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=5" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

isalirezag: <p><a class="mention" href="/u/innovarul">@InnovArul</a>  <a class="mention" href="/u/justusschock">@justusschock</a><br>
I deactivated it, but it is still not giving the answer it should…</p>
<p>Update:<br>
It is a little wierd…<br>
When i do<br>
<code>Input = torch.rand(1,1,6,6)</code><br>
it works</p>
<p>but when i do:<br>
<code>Input = torch.rand(1,2,6,6)</code><br>
it doesnot</p>

InnovArul: <p>Ok. well, you are having 2 channels (which I didn’t notice). The conv layer will multiply the kernel with input and add up the results for every position.</p>
<p>Try having only one channel and check the results.</p>

isalirezag: <p>yeah exactly!<br>
I just noticed that…</p>
<p>Do you know what i should do to make it work for batchsize and channel size more than 1?</p>

InnovArul: <p>you can use group convolutions.</p>
<p><code>Guass = nn.Conv2d(Input.size(1), Input.size(1), 3, padding = 1, bias=False, groups=Input.size(1))</code></p>

isalirezag: <p>I have never used that before! but it gives what i want!!<br>
Thank you <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=5" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

justusschock: <p>and you could also use the functional API which removes the necessarity to change the weigthts by hand since you could simply pass the weights to the function.</p>

isalirezag: <p>hmmm what do you mean? <img src="https://discuss.pytorch.org/images/emoji/apple/thinking.png?v=5" title=":thinking:" class="emoji" alt=":thinking:"></p>

justusschock: <pre><code class="lang-auto">x = torch.rand(1, 1, 64, 64)
gauss_kernel = torch.Tensor([[0, 0, 0], [0, 1, 0], [0, 0, 0]]).unsqueeze(0).unsqueeze(0)
out = F.conv2d(x, gauss_kernel, padding=1)
print(x)
print(gauss_kernel)
print(out)
tensor([[[[0.7888, 0.7222, 0.9251,  ..., 0.1763, 0.8585, 0.7747],
          [0.8203, 0.2307, 0.4474,  ..., 0.8498, 0.3399, 0.2610],
          [0.0001, 0.2678, 0.2113,  ..., 0.9698, 0.3422, 0.1166],
          ...,
          [0.7921, 0.1250, 0.1268,  ..., 0.8102, 0.1775, 0.4617],
          [0.1761, 0.6137, 0.6097,  ..., 0.0786, 0.8547, 0.4948],
          [0.7365, 0.6266, 0.6305,  ..., 0.6367, 0.0811, 0.8240]]]])
tensor([[[[0., 0., 0.],
          [0., 1., 0.],
          [0., 0., 0.]]]])
tensor([[[[0.7888, 0.7222, 0.9251,  ..., 0.1763, 0.8585, 0.7747],
          [0.8203, 0.2307, 0.4474,  ..., 0.8498, 0.3399, 0.2610],
          [0.0001, 0.2678, 0.2113,  ..., 0.9698, 0.3422, 0.1166],
          ...,
          [0.7921, 0.1250, 0.1268,  ..., 0.8102, 0.1775, 0.4617],
          [0.1761, 0.6137, 0.6097,  ..., 0.0786, 0.8547, 0.4948],
          [0.7365, 0.6266, 0.6305,  ..., 0.6367, 0.0811, 
</code></pre>
<p>This way you don’t have to wrap your kernel into a Parameter and you don’t have to modify the weights by hand, it might also reduce some memory (which really is not that relevant in this small example).</p>

isalirezag: <p>if i have an input of size</p>
<pre><code class="lang-auto">x = torch.rand(1, 3, 64, 64)
</code></pre>
<p>how would you do it to have a output of size (1,3,64,64)?</p>

justusschock: <p>Probably use a 1x1 kernel?</p>