NumPy 卷积定理
NumPy Convolution Theorem
我是卷积的新手,因此想通过使用 FFT 将两个一维信号卷积在一起来向自己证明卷积定理。但是,我的代码与np.convolve
.
得到的结果不一致
我使用了这个 :
中的简单实现
import numpy as np
def Convolution(array,kernel):
return np.real(np.fft.ifft( np.fft.fft(array)*np.fft.fft(kernel) ))
a_flat = [ 1., 2., 3., 0., 0., 4., 5., 6., 0., 0. , 7., 8., 9.]
k_flat = [ 1,2 ,1 ,0,0 ,0 ,0,0 ,0 ,0,-1,-2,-1]
my_convolution = Convolution(a_flat, k_flat)
np_convolution = np.convolve(a_flat, k_flat)
print(my_convolution)
print("")
print(np_convolution)
输出为:
[ 19. 10. 4. -5. -17. -13. 7. 13. -5. -26. -20. 9. 24.]
[ 1. 4. 8. 8. 3. 4. 13. 20. 17. 6. 6. 18. 24. 18. 6. -4. -13. -20. -17. -6. -7. -22. -32. -26. -9.]
我显然遗漏了一些东西。有人可以指出我的疏忽吗?
注意你的锚点在内核中的位置,通常是中位数,在你的情况下是中间的 0,你仍然应该确保它是正确的。
参考@Paul R 的回答,决定您要使用哪种填充(零填充、复制边界区域等),因为这会影响您的输出。
一个卷积的结果是N+M-1,例如长于任一输入。所以你的 FFT 需要那么长或更长。
一个FFT/IFFT会将快速卷积结果包裹起来,并将其混合成循环卷积。但是,如果您在末尾用大量零填充数据,则混合将很容易取消混合。
@hotpaw2 说的。总是更好地绘制它:
import numpy as np
import matplotlib.pyplot as p
%matplotlib inline
def Convolution(array,kernel):
return np.real(np.fft.ifft( np.fft.fft(array)*np.fft.fft(kernel) ))
a_flat = [ 1., 2., 3., 0., 0., 4., 5., 6., 0., 0. , 7., 8., 9.]
k_flat = [ 1,2,1,0,0,0,0,0,0,0,-1,-2,-1]
a_flat= np.pad(a_flat, (25, 25), 'constant', constant_values=(0, 0)).tolist()
k_flat= np.pad(k_flat, (25, 25), 'constant', constant_values=(0, 0)).tolist()
my_convolution = Convolution(a_flat, k_flat)
np_convolution = np.convolve(a_flat, k_flat)
fig,ax = p.subplots(3,figsize=(12,5))
ax[0].plot(a_flat)
ax[1].plot(k_flat)
ax[2].plot(np.roll(my_convolution, 30),'.-',lw=0.5,label='myconv'); # arbitrary shift here
ax[2].plot(np.roll(np_convolution, 0),'.-',lw=3,alpha=0.3,label='npconv');
p.legend()
很好的例子,顺便说一句。
我是卷积的新手,因此想通过使用 FFT 将两个一维信号卷积在一起来向自己证明卷积定理。但是,我的代码与np.convolve
.
我使用了这个
import numpy as np
def Convolution(array,kernel):
return np.real(np.fft.ifft( np.fft.fft(array)*np.fft.fft(kernel) ))
a_flat = [ 1., 2., 3., 0., 0., 4., 5., 6., 0., 0. , 7., 8., 9.]
k_flat = [ 1,2 ,1 ,0,0 ,0 ,0,0 ,0 ,0,-1,-2,-1]
my_convolution = Convolution(a_flat, k_flat)
np_convolution = np.convolve(a_flat, k_flat)
print(my_convolution)
print("")
print(np_convolution)
输出为:
[ 19. 10. 4. -5. -17. -13. 7. 13. -5. -26. -20. 9. 24.]
[ 1. 4. 8. 8. 3. 4. 13. 20. 17. 6. 6. 18. 24. 18. 6. -4. -13. -20. -17. -6. -7. -22. -32. -26. -9.]
我显然遗漏了一些东西。有人可以指出我的疏忽吗?
注意你的锚点在内核中的位置,通常是中位数,在你的情况下是中间的 0,你仍然应该确保它是正确的。 参考@Paul R 的回答,决定您要使用哪种填充(零填充、复制边界区域等),因为这会影响您的输出。
一个卷积的结果是N+M-1,例如长于任一输入。所以你的 FFT 需要那么长或更长。
一个FFT/IFFT会将快速卷积结果包裹起来,并将其混合成循环卷积。但是,如果您在末尾用大量零填充数据,则混合将很容易取消混合。
@hotpaw2 说的。总是更好地绘制它:
import numpy as np
import matplotlib.pyplot as p
%matplotlib inline
def Convolution(array,kernel):
return np.real(np.fft.ifft( np.fft.fft(array)*np.fft.fft(kernel) ))
a_flat = [ 1., 2., 3., 0., 0., 4., 5., 6., 0., 0. , 7., 8., 9.]
k_flat = [ 1,2,1,0,0,0,0,0,0,0,-1,-2,-1]
a_flat= np.pad(a_flat, (25, 25), 'constant', constant_values=(0, 0)).tolist()
k_flat= np.pad(k_flat, (25, 25), 'constant', constant_values=(0, 0)).tolist()
my_convolution = Convolution(a_flat, k_flat)
np_convolution = np.convolve(a_flat, k_flat)
fig,ax = p.subplots(3,figsize=(12,5))
ax[0].plot(a_flat)
ax[1].plot(k_flat)
ax[2].plot(np.roll(my_convolution, 30),'.-',lw=0.5,label='myconv'); # arbitrary shift here
ax[2].plot(np.roll(np_convolution, 0),'.-',lw=3,alpha=0.3,label='npconv');
p.legend()
很好的例子,顺便说一句。