pythonscipyconvolution

Why are the values different when performing convolution on 1D array with product of FFTs?


As we know, FFT inverse of (FFT(A) elementwise multiplied with FFT(B)) may be the same as the convolution of A and B.

However, if I do this in Python:

import numpy as np
import scipy

c = scipy.fft.fft([3, 4, 1, 2])
d = scipy.fft.fft([2, 5, 4, 9])
print(scipy.fft.ifft((c * d)))
# [56.+0.j 40.+0.j 52.+0.j 52.-0.j]

print(np.convolve([3, 4, 1, 2], [2, 5, 4, 9]))
# [ 6 23 34 52 50 17 18]

Why are the values different?


Solution

  • FFT uses circular convolution, as compared to linear convolution.

    enter image description here

    You can use zero-padding before performing FFT to get the same result as with linear convolution:

    import numpy as np
    import scipy.fft
    
    
    def _conv(a, b):
        azero, bzero = np.pad(a, (0, len(b) - 1)), np.pad(b, (0, len(a) - 1))
        c, d = scipy.fft.fft(azero), scipy.fft.fft(bzero)
        iFFT = scipy.fft.ifft(c * d)
        return np.round(iFFT), np.convolve(a, b)
    
    
    print(_conv(np.array([3, 4, 1, 2]), np.array([2, 5, 4, 9])))
    

    Prints

    (array([ 6.+0.j, 23.+0.j, 34.+0.j, 52.+0.j, 50.+0.j, 17.+0.j, 18.+0.j]), array([ 6, 23, 34, 52, 50, 17, 18]))