I noticed that when I use conv(a, b, 'same') in matlab, it would return say M of length 200, but when I use numpy.convolve(a, b, 'same') it would return N of length 200, but shifted by one element compared to M (N[1:] would be the same as M[0:-1] and M[-1] would not be in N, N[0] not in M), how can I fix this?
I can cut off the first element of N, but is there a way I can get the last element of M without going through some hassles?
The np. convolve() is a built-in numpy library method used to return discrete, linear convolution of two one-dimensional vectors. The numpy convolve() method accepts three arguments which are v1, v2, and mode, and returns discrete the linear convolution of v1 and v2 one-dimensional vectors.
The convolution of two vectors, u and v , represents the area of overlap under the points as v slides across u . Algebraically, convolution is the same operation as multiplying polynomials whose coefficients are the elements of u and v . Let m = length(u) and n = length(v) .
The same concept of convolving is used in Python. The array is considered as a signal which is used in the SciPy Convolve function to perform convolution over multiple one-dimensional arrays. The SciPy Convolve is an N-dimensional array. It is usually two or more 1-D sequences.
An array in numpy is a signal. The convolution of two signals is defined as the integral of the first signal, reversed, sweeping over ("convolved onto") the second signal and multiplied (with the scalar product) at each position of overlapping vectors.
My guess is that the length of the shorter input array is even. In this case, there is an ambiguity in how it should be handled when the method is "same". Apparently Matlab and numpy adopted different conventions.
There is an example of the use of the 'same' method on the Matlab documentation web page (http://www.mathworks.com/help/matlab/ref/conv.html):
> u = [-1 2 3 -2 0 1 2];
> v = [2 4 -1 1];
> w = conv(u,v,'same')
w =
15 5 -9 7 6 7 -1
The first term, 15, is (1)*(0) + (-1)*(-1) + (4)*(2) + (2)*(3)
, and the last term, -1, is (1)*(1) + (-1)*(2) + (4)*(0) + (2)*(0)
. You can interpret that as padding u
to be [0 -1 2 3 -2 0 1 2 0 0], and then using the 'valid' method.
With numpy:
In [24]: u
Out[24]: array([-1, 2, 3, -2, 0, 1, 2])
In [25]: v
Out[25]: array([ 2, 4, -1, 1])
In [26]: np.convolve(u, v, 'same')
Out[26]: array([ 0, 15, 5, -9, 7, 6, 7])
The first term, 0, is (1)*(0) + (-1)*(0) + (4)*(-1) + (2)*(2)
, and the last term, 7, is (1)*(0) + (-1)*(1) + (4)*(2) + (2)*(0)
. That result can be interpreted as padding u
to be [0, 0, -1, 2, 3, -2, 0, 1, 2, 0] and then using the 'valid' method.
By thinking about the 'same' method as being equivalent to padding the longer argument with p
zeros (where p
is one less than the length of the shorter input) and then applying the 'valid' method, you can see that when p
is odd (i.e. the shorter length is even), a choice is required for which end gets the extra 0. Matlab and numpy use different choices.
To implement the Matlab version of the 'same' method, you could do the padding yourself and use the 'valid' method with np.convolve
. For example,
In [45]: npad = len(v) - 1
In [46]: u_padded = np.pad(u, (npad//2, npad - npad//2), mode='constant')
In [47]: np.convolve(u_padded, v, 'valid')
Out[47]: array([15, 5, -9, 7, 6, 7, -1])
Or you could apply the 'full' method, and then slice out the part that is equivalent to Matlab's 'same' method:
In [62]: npad = len(v) - 1
In [63]: full = np.convolve(u, v, 'full')
In [64]: first = npad - npad//2
In [65]: full[first:first+len(u)]
Out[65]: array([15, 5, -9, 7, 6, 7, -1])
Other implementations are possible. Which one to use depends on how much you want to avoid extra copying, extra memory use and extra computation.
If the shorter input array has an odd length, the results in Matlab and numpy should be the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With