Comparing MatLab's conv2 with scipy's convolve2d

时间:2015-06-30 13:44:08

标签: python matlab scipy convolution moving-average

I am trying to compute S3x3 moving averages, using asymmetric weights, as described in this MatLab example and I am unsure if my interpretation of the following is correct when translating from MatLab:

  1. Have I set up my matrices in the same way?
  2. Does scipy.signal.convolve2d do the same as MatLab's conv2d in this instance?
  3. Why is my fit so bad?!

In MatLab, the filter is given and applied as:

% S3x3 seasonal filter
% Symmetric weights
sW3 = [1/9;2/9;1/3;2/9;1/9];
% Asymmetric weights for end of series
aW3 = [.259 .407;.37 .407;.259 .185;.111 0];

% dat contains data - simplified adaptation from link above
ns = length(dat) ; first = 1:4 ; last = ns - 3:ns; 
trend = conv(dat, sW3, 'same');
trend(1:2) = conv2(dat(first), 1, rot90(aW3,2), 'valid');
trend(ns-1:ns) = conv2(dat(last), 1, aW3, 'valid');

I have interpreted this in python using my own data, I have assumed in doing so that ; in MatLab matrices means new row and that a space means new column

import numpy as np
from scipy.signal import convolve2d

dat = np.array([0.02360784,  0.0227628 ,  0.0386366 ,  0.03338596,  0.03141621, 0.03430469])
dat = dat.reshape(dat.shape[0], 1) # in columns

sW3 = np.array([[1/9.],[2/9.],[1/3.],[2/9.],[1/9.]])
aW3 = np.array( [[ 0.259,  0.407],
                 [ 0.37 ,  0.407],
                 [ 0.259,  0.185],
                 [ 0.111,  0.   ]])

trend = convolve2d(dat, sW3, 'same')
trend[:2] = convolve2d(dat[:2], np.rot90(aW3,2), 'same')
trend[-2:] = convolve2d(dat[-2:], np.rot90(aW3,2), 'same')

Plotting the data, the fit is pretty bad...

import matplotlib.pyplot as plt
plt.plot(dat, 'grey', label='raw data', linewidth=4.)
plt.plot(trend, 'b--', label = 'S3x3 trend')
plt.legend()
plt.plot()

enter image description here

1 个答案:

答案 0 :(得分:0)

解决。

enter image description here

事实证明,这个问题与来自docs的MatLab conv2d和scipy' convolve2d的细微差别有关。

  

C = conv2(h1,h2,A) 首先使用向量Ah1每列进行卷积,然后将每行进行卷积向量h2

的结果

这意味着我的代码中边缘实际发生的事情是不正确的。实际上应该是每个端点卷积的以及aW3的相关列

e.g。

nwtrend = np.zeros(dat.shape)
nwtrend = convolve2d(dat, sW3, 'same')

for i in xrange(np.rot90(aW3, 2).shape[1]):
    nwtrend[i] = np.convolve(dat[i,0], np.rot90(aW3, 2)[:,i], 'same').sum()

for i in xrange(aW3.shape[1]):
    nwtrend[-i-1] = np.convolve(dat[-i-1,0], aW3[:,i], 'same').sum()

获取上面的输出

plt.plot(nwtrend, 'r', label='S3x3 new',linewidth=2.)
plt.plot(trend, 'b--', label='S3x3 old')
plt.legend(loc='lower centre')
plt.show()