Convolution (NOT cross-correlation) in pytorch

I have a network ( https://github.com/TheAbhiKumar/tensorflow-value-iteration-networks ) that I am trying to implement in pytorch (I am very new to pytorch, not at all new to machine learning).

In short, I can't figure out how to implement a "clean" convolution in pytorch. In tensor flow, this can be done as follows:

def conv2d_flipkernel(x, k, name=None): return tf.nn.conv2d(x, flipkernel(k), name=name, strides=(1, 1, 1, 1), padding='SAME') 

With flipkernel function:

 def flipkernel(kern): return kern[(slice(None, None, -1),) * 2 + (slice(None), slice(None))] 

How can something like this be done in pytorch?

+6
source share
1 answer

TL; DR Use the convolution from the torch.nn.fuctional.conv2d function toolbar, not torch.nn.conv2d and flip the filter around the vertical and horizontal axis.


torch.nn.conv2d is a convolutional layer for the network. Since the weights are studied, it doesn’t matter if it is implemented using cross-correlation, because the network will simply learn the mirror version of the kernel (thanks @etarion for this clarification).

torch.nn.fuctional.conv2d does a convolution with the inputs and weights provided as arguments, similar to the tensorflow function in your example. I wrote a simple test to determine if the tensor flow function actually performs cross-correlation, and you need to flip the filter for correct convolutional results.

 import torch import torch.nn.functional as F import torch.autograd as autograd import numpy as np #A vertical edge detection filter. #Because this filter is not symmetric, for correct convolution the filter must be flipped before element-wise multiplication filters = autograd.Variable(torch.FloatTensor([[[[-1, 1]]]])) #A test image of a square inputs = autograd.Variable(torch.FloatTensor([[[[0,0,0,0,0,0,0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0,0,0,0,0,0,0]]]])) print(F.conv2d(inputs, filters)) 

Displays

 Variable containing: (0 ,0 ,.,.) = 0 0 0 0 0 0 0 1 0 0 -1 0 0 1 0 0 -1 0 0 1 0 0 -1 0 0 0 0 0 0 0 [torch.FloatTensor of size 1x1x5x6] 

This result is the result of cross-correlation. So we need to flip the filter

 def flip_tensor(t): flipped = t.numpy().copy() for i in range(len(filters.size())): flipped = np.flip(flipped,i) #Reverse given tensor on dimention i return torch.from_numpy(flipped.copy()) print(F.conv2d(inputs, autograd.Variable(flip_tensor(filters.data)))) 

The new conclusion is the correct result for the convolution.

 Variable containing: (0 ,0 ,.,.) = 0 0 0 0 0 0 0 -1 0 0 1 0 0 -1 0 0 1 0 0 -1 0 0 1 0 0 0 0 0 0 0 [torch.FloatTensor of size 1x1x5x6] 
+11
source

Source: https://habr.com/ru/post/1265812/


All Articles