numpy卷积结果偏移求助:mode='same'时位置不符合预期
修正numpy.convolve中mode='same'的卷积结果位置偏移问题
我使用Python的numpy.convolve对两个概率分布图执行卷积运算,为了和原始分布对比选择了mode='same'参数,但实际结果位置不符合预期:按数学逻辑,卷积峰值应处于两个分布之间或更大的x值位置,实际却发生了偏移。切换到mode='full'模式时,卷积的x轴位置符合预期,但由于绘图模块healpy对数组长度有特定要求,必须使用mode='same',因此需要修正该模式下的位置偏移问题。
测试复现代码
import numpy as np import matplotlib.pyplot as plt mu1=2 sigma1=1 mu2=1 sigma2=0.5 x=np.linspace(-7, 7, num=1000) p = np.exp(-0.5 * ((x - mu1) / sigma1)**2) / (sigma1 * np.sqrt(2 * np.pi)) p /=np.sum(p) q = np.exp(-0.5 * ((x - mu2) / sigma2)**2) / (sigma2 * np.sqrt(2 * np.pi)) q /=np.sum(q) c=np.convolve(p, q, mode='full') c2=np.convolve(p, q, mode='same') plt.plot(x, p, label='p') plt.plot(x, q, label='q') plt.plot(np.linspace(-7, 7, num=len(c)), c, label='Convolution of p and q mode=\'full\'') plt.plot(x, c2, label='Convolution of p and q with mode=\'same\'') plt.legend()
问题原因与修正方法
核心原因
numpy.convolve的mode='same'是从数组索引中心截取与输入等长的结果,而非基于x轴物理位置的中心。当原始分布的均值不在x轴中心时,截取结果会出现偏移。另外,测试代码中给mode='full'的卷积强制映射到-7~7区间也是错误的——数学上两个分布卷积的x轴范围应为[x_min_p+x_min_q, x_max_p+x_max_q],原代码的压缩只是巧合让峰值位置看起来正确。
具体修正步骤
计算
mode='full'的正确x轴范围
卷积的每个元素对应原始分布的x值之和,因此正确的x轴起始为x[0]+x[0],步长与原数组一致:dx = x[1] - x[0] x_full = x[0] + x[0] + np.arange(len(c)) * dx推导
mode='same'对应的x轴位置mode='same'的结果是从mode='full'的结果中截取中间段,找到截取的起始索引后,即可生成对应的正确x轴:start_idx = (len(c) - len(x)) // 2 x_same = x_full[start_idx : start_idx + len(x)]修正后的完整代码
import numpy as np import matplotlib.pyplot as plt mu1=2 sigma1=1 mu2=1 sigma2=0.5 x=np.linspace(-7, 7, num=1000) dx = x[1] - x[0] p = np.exp(-0.5 * ((x - mu1) / sigma1)**2) / (sigma1 * np.sqrt(2 * np.pi)) p /=np.sum(p) q = np.exp(-0.5 * ((x - mu2) / sigma2)**2) / (sigma2 * np.sqrt(2 * np.pi)) q /=np.sum(q) c=np.convolve(p, q, mode='full') c2=np.convolve(p, q, mode='same') # 生成正确的full卷积x轴 x_full = x[0] + x[0] + np.arange(len(c)) * dx # 生成same卷积对应的正确x轴 start_idx = (len(c) - len(x)) // 2 x_same = x_full[start_idx : start_idx + len(x)] plt.plot(x, p, label='p') plt.plot(x, q, label='q') plt.plot(x_full, c, label='Convolution (mode=\'full\')') plt.plot(x_same, c2, label='Convolution (mode=\'same\')') plt.legend() plt.show()
修正后,mode='same'的卷积结果x轴位置会完全符合数学预期,同时保持数组长度满足healpy的要求。
内容的提问来源于stack exchange,提问作者Jacob Ayre
相关产品推荐
相关产品推荐

