Functional Conv2d Produces Different Results VS Scipy Convolved2d

Hello,

Running the follow code I get different convolution results for a single image and filter between scipy convolve2d and torch.nn.functional.conv2d().

The filter is size 3 thus a padding size of (1,1) should be correct regardless.

Why does this difference occur?

import numpy as np
import torch
import scipy
from torch.nn import functional as F
from scipy import signal

imgSize = 5

testImg = np.array([[1.0, 2, 3, 4, 5], [4, 5, 6, 7, 8], [7, 8, 9, 10, 11], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20]])
testFilt = np.array([[1, 2, 5], [3.0, 4, 2], [7, 8, 9]])

# Numpy test
npConv = scipy.signal.convolve2d(testImg, testFilt, mode='same')

filt = torch.from_numpy(testFilt).type(torch.float32)
filt = filt.unsqueeze(0).unsqueeze(0)

img = torch.from_numpy(testImg).type(torch.float32)
img = img.unsqueeze(0).unsqueeze(0)

# Padding pads on both sides symmetrically
# Doesn't match scipy?
funOut = F.conv2d(img, filt, bias=None, padding=1, stride=(1, 1))

print(npConv)
print(funOut)

PyTorch (and other ML frameworks that I know about) actually implement cross-correlation in the functions named convolution.

The difference is just the reversal of the filter.

filt = torch.from_numpy(np.ascontiguousarray(testFilt[::-1, ::-1])).type(torch.float32)
filt = filt.unsqueeze(0).unsqueeze(0)

Now it produces the same results.

4 Likes