0

I want to make convolution of matrix

np.random.seed(0)
m_numpy = np.random.choice([0,1],p=(0.5,0.5),size=(6,6))
m = torch.from_numpy(Z_numpy).type(torch.FloatTensor)
tensor([[1., 1., 1., 1., 0., 1.],
        [0., 1., 1., 0., 1., 1.],
        [1., 1., 0., 0., 0., 1.],
        [1., 1., 1., 1., 0., 1.],
        [0., 1., 0., 1., 1., 0.],
        [0., 1., 0., 1., 0., 1.]])

with kernel:

krnl = torch.tensor([[1,1,1],
                            [1,0,1],
                            [1,1,1]])

krnl
tensor([[1, 1, 1],
        [1, 0, 1],
        [1, 1, 1]])

However using function conv2d from torch.nn.functional I don't see where to write those tensors in it. Doing this conv2d(m, krnl,mode='same') brings error:

TypeError: conv2d() received an invalid combination of arguments - got (Tensor, Tensor, mode=str), but expected one of:
 * (Tensor input, Tensor weight, Tensor bias, tuple of ints stride, tuple of ints padding, tuple of ints dilation, int groups)
 * (Tensor input, Tensor weight, Tensor bias, tuple of ints stride, str padding, tuple of ints dilation, int groups)

How to do that?

Ivan
  • 34,531
  • 8
  • 55
  • 100
  • https://discuss.pytorch.org/t/setting-custom-kernel-for-cnn-in-pytorch/27176 Does this help ? – Balaji Oct 03 '21 at 12:44

2 Answers2

1

Both the weight tensor and the input tensor must be four-dimensional:

  • The shape of the input tensor is (batch_size, n_channels, height, width). Here you are looking to infer from a single-channel 6x6 instance, i.e. a shape of (1, 1, 6, 6).

  • The shape of the weight tensor provided to F.conv2d corresponds to (n_filters, n_channels, kernel_height, kernel_width). In your case it seems you only have a single filter with a single channel, with kernel_height and kernel_width both equal to 3.

Also, both operands must have a dtype of float.

>>> krnl = tensor([[1., 1., 1.],
                   [1., 0., 1.],
                   [1., 1., 1.]])

>>> F.conv2d(m.reshape(1,1,*m.shape), krnl.reshape(1,1,*krnl.shape), padding='same')
tensor([[[[2., 4., 4., 3., 4., 2.],
          [5., 6., 5., 4., 4., 3.],
          [4., 6., 6., 4., 5., 3.],
          [4., 5., 5., 3., 5., 2.],
          [4., 4., 7., 4., 5., 3.],
          [2., 1., 4., 2., 4., 1.]]]])

Alternatively, to reshape to (1, 1, h, w), you could do:

>>> F.conv2d(m[None, None], krnl[None, None], padding='same')
# yields the same result

With import torch.nn.functional as F

Ivan
  • 34,531
  • 8
  • 55
  • 100
0

In the below code I've changes the dimesions of m_numpy to (1,1,6,6), Conv2d expects this dimension, then matched the kernel dimesnion as well, used the functional module's conv2d as described in here

import numpy as np
import torch
import torch.nn.functional as F

np.random.seed(0)
m_numpy = np.random.choice([0,1],p=(0.5,0.5),size=(1,1,6,6))
m = torch.from_numpy(m_numpy).type(torch.FloatTensor)

print(m)

weights = torch.tensor([[[[1.,1.,1.],
                          [1.,0.,1.],
                          [1.,1.,1.]]]])

print(weights)

output = F.conv2d(m, weights, padding = 1)

print(output)

Gives output

tensor([[[[1., 1., 1., 1., 0., 1.],
          [0., 1., 1., 0., 1., 1.],
          [1., 1., 0., 0., 0., 1.],
          [1., 1., 1., 1., 0., 1.],
          [0., 1., 0., 1., 1., 0.],
          [0., 1., 0., 1., 0., 1.]]]])
tensor([[[[1., 1., 1.],
          [1., 0., 1.],
          [1., 1., 1.]]]])
tensor([[[[2., 4., 4., 3., 4., 2.],
          [5., 6., 5., 4., 4., 3.],
          [4., 6., 6., 4., 5., 3.],
          [4., 5., 5., 3., 5., 2.],
          [4., 4., 7., 4., 5., 3.],
          [2., 1., 4., 2., 4., 1.]]]])
Balaji
  • 795
  • 1
  • 2
  • 10