How to create a novel convolution kernel?

We can use torch.nn.Conv2d to create an usual convolution layer, but if I want to creat a convolution layer with a kernel of novel shape, such as ‘T’ shape(means with kernel weight of [w1 w2 w3; 0 w4 0; 0 w5 0] ), what should I do?
Could somebody help me? Thanks very much!

you can make use of torch.nn.functional.conv2d().

import torch.nn.functional as F
kernel = torch.Tensor([[[[1,2,3], [0,4,0], [0,5,0]]]])
data = torch.randn(1,1,10,10)
output = F.conv2d(data, kernel)
1 Like

Thanks for your answer! But I want to train the layer in a network, means w1 to w5 are learnable. Just like dilate convolution, some weights are 0, and others are learnable. Do you know how to do this?

If you initialize your kernel with zeros in the right places, you could probably use register_hook to zero the corresponding gradients to avoid learning those parameters.

you can still use function approach

class NovelConv(nn.Module):
    def __init__(self):
        self.W = nn.Parameter(torch.Tensor([[w1,w2,w3],[w4,0,0],[w5,0,0]]))
    def forward(self,x):
        return F.conv2d(x, self.W)

Backpropogation will work by doing this

Thank you! As far as I know, register_hook is used to get intermediate results. How to use register_hook to zero the gradients, could you please explain it more specifically?

Thank you! In this way, I need to extract w1 to w5 from original layer, and give it to W, how to do this?

thank you! I used your function .but have the NameError: name ‘w1’ is not to solve it ?

do you solve this question?I meet the same question

I found a solution for a problem similar that yours. Check the code below for a convolution block with symmetric coefficients

I initially tried to create the weight matrix as @Naman-ntc but the graph was broken and the gradients did not flow to the scalar variables

For this reason I create the weight matrix by summing the coefficients to a zero matrix. Any other simpler alternatives are welcome

class Conv2d_symmetric(nn.Module):
    def __init__(self):
        super(Conv2d_simple, self).__init__()

        self.a = nn.Parameter(torch.randn(1))
        self.b = nn.Parameter(torch.randn(1))
        self.c = nn.Parameter(torch.randn(1))

        self.bias = None
        self.stride = 2
        self.padding = 1
        self.dilation = 1
        self.groups = 1

    def forward(self, input):

        #in case we use gpu we need to create the weight matrix there
        device = self.a.device

        weight = torch.zeros((1,1,3,3)).to(device)
        weight[0,0,0,0] += self.c[0]
        weight[0,0,0,1] += self.b[0]
        weight[0,0,0,2] += self.c[0]
        weight[0,0,1,0] += self.b[0]
        weight[0,0,1,1] += self.a[0]
        weight[0,0,1,2] += self.b[0]
        weight[0,0,2,0] += self.c[0]
        weight[0,0,2,1] += self.b[0]
        weight[0,0,2,2] += self.c[0]

        # print("weight= ", weight)
        # print("inout = ", input)
        return F.conv2d(input, weight, self.bias, self.stride,
                        self.padding, self.dilation, self.groups)