Setting weights for a custom convolution layer

Ron3: <p>Hello I am trying to implement a custom convolution, which is based around a local binary filter.<br>
In order to do so, I have to create multiple convolutions whose weights can’t be changed and just have 0, apart from the middle which is 0 and then one 1 in a location around it, so for 3x3 conv it would be 8 different masks.<br>
However with the code I wrote I am not able to set the weights in an explicit manner.</p>
<p>count = 0<br>
self.conv = nn.Conv2d(1, 1, m, bias=False)<br>
self.conv = self.conv.weight<br>
self.conv.requires_grad = False<br>
for u in range(m*m-1):<br>
for i in range(m):<br>
for j in range(m):<br>
if u == count:<br>
self.conv.weight[i][j] = 1<br>
else:<br>
self.conv.weight[i][j] = 0<br>
self.conv.weight[round(m/2)][round(m/2)] = -1</p>
<pre><code>        count = count + 1
        print(self.conv)
</code></pre>
<p>doing it this way only delivers me this error message:<br>
Traceback (most recent call last):<br>
File “C:\Users\Ron Rödel\PycharmProjects\lbcnnn\main.py”, line 46, in <br>
o = Lbcnn(3)<br>
File “C:\Users\Ron Rödel\PycharmProjects\lbcnnn\main.py”, line 25, in <strong>init</strong><br>
self.conv.weight[i][j] = 1<br>
AttributeError: ‘Parameter’ object has no attribute ‘weight’</p>
<p>If I apply what I read with is instance it just seems to ignore the if statement alltogether<br>
here is how I wrote the if isInstance statement:<br>
if isinstance(u == count, nn.Conv2d):<br>
self.conv.weight[i][j] = 1<br>
I get to the print statement now, but now of the weights have been changed.</p>
<p>So all in all I am just confused and I apologize for the bad formating</p>

ptrblck: <p>You are re-assigning <code>self.conv</code> to the <code>self.conv.weight</code>:</p>
<pre><code class="lang-python">self.conv = self.conv.weight
</code></pre>
<p>and are then trying to access the <code>.weight</code> attribute again, which will fail.<br>
Directly assigning values to the <code>.weight</code> will work:</p>
<pre><code class="lang-python">conv = nn.Conv2d(1, 1, 3)
with torch.no_grad():
    conv.weight[0, 0, 1, 1] = 0.
print(conv.weight)
# Parameter containing:
# tensor([[[[ 0.2617,  0.0339,  0.2769],
#           [ 0.2088,  0.0000, -0.2846],
#           [-0.2943, -0.0077, -0.0271]]]], requires_grad=True)
</code></pre>

Ron3: <p>Directly assigning it to .weight got rid of the Attribute error, however now I am facing an indexing error. To clarify I only want to assign a weight to one specific location at a time.<br>
And still thanks for the first tip</p>

ptrblck: <p>I don’t know what kind of indexing error you are seeing so feel free to post a code snippet reproducing the error in case you get stuck.</p>

Ron3: <p>I can point it down somewhat<br>
if I write it as:<br>
print(self.conv.weight[0][0]), I get a print of the tensor<br>
or if I assign it like so:<br>
self.conv.weight[0] = 1<br>
I get a tensor where all values are 1<br>
if I write it like self.conv.weight[1] = 1<br>
then I get this error:</p>
<pre><code class="lang-auto">IndexError: index 1 is out of bounds for dimension 0 with size 1
</code></pre>
<p>The thing I want to do is, to assign a value directly to a spot of the filter, so I figured<br>
if I were to it like so it should work:</p>
<pre><code class="lang-auto">            for i in range(m):
                for j in range(m):
                    if u == count:
                        with torch.no_grad():
                            self.conv.weight[i][j] = 1
</code></pre>
<p>I get the aformentioned error</p>

ptrblck: <p>The shape of the filter is <code>[out_channels, in_channels, height, width]</code>. If you want to access the spatial dimensions (height and width) index <code>dim2</code> and <code>dim3</code> as seen in my example.</p>

Ron3: <p>thanks alot, that did the trick</p>