matplotlib.mlab.psd(...)
和scipy.signal.welch(...)
都实施了Welch的平均周期图方法来估算信号的功率谱密度(PSD)。假设将等效参数传递给每个函数,则返回的PSD应该是等效的。
然而,使用简单的正弦测试函数,当每个窗口使用的点数(nperseg
的{{1}}关键字; scipy.signal.welch
关键字时,两种方法之间存在系统差异for NFFT
) even ,如下所示,每个窗口64点的情况
上图显示了通过两种方法计算的PSD,而下图显示了它们的相对误差(即两个PSD的绝对差除以它们的绝对平均值)。较大的相对误差表明两种方法之间存在较大的不一致。
当每个窗口使用的点数奇数时,这两个函数具有更好的一致性,如下所示相同的信号,但每个窗口处理65个点< / p>
在信号中添加其他特征(例如噪声)会稍微减少这种影响,但它仍然存在,当每个窗口使用偶数个点时,两种方法之间的相对误差约为10%。 (我意识到,对于每个窗口65个点计算的PSD的最高频率的相对误差相对较大。但是,这是在信号的奈奎斯特频率,并且我不太关心特征在如此高的频率下。当每个窗口的点数是偶数时,我更关心大部分信号带宽上的大而系统的相对误差。
这种差异是否有原因?一种方法在准确性方面是否优于另一种方法?我使用scipy版本0.16.0和matplotlib版本1.4.3。
用于生成上述图的代码如下所示。对于纯正弦信号,设置mlab.psd
;对于有噪声的信号,将A_noise = 0
设置为有限值。
A_noise
答案 0 :(得分:8)
虽然参数可能看起来是等效的,但窗口参数对于偶数大小的窗口可能略有不同。更具体地说,除非提供特定的窗口向量,否则scipy的welch
函数使用的窗口是用
win = get_window(window, nperseg)
使用默认参数fftbins=True
,并根据scipy documentation:
如果为True,则创建一个“定期”窗口,准备与ifftshift一起使用,并乘以fft的结果(另请参见fftfreq)。
这导致生成的窗口长度均匀。从this section of the Window function entry on Wikipedia开始,与Matplotlib的window_hanning
相比,这可以带来轻微的性能优势,它始终返回对称版本。
要使用相同的窗口,您可以明确指定两个PSD估计函数的窗口向量。例如,您可以使用以下方法计算此窗口:
win = scipy.signal.get_window('hanning',nperseg)
使用此窗口作为参数(在两个函数中都带有window=win
)将给出以下图表,您可能会注意到两个PSD估计函数之间更接近的一致性:
或者,假设您不想要周期性窗口属性,您也可以使用:
win = mlab.window_hanning(np.ones(nperseg)) # or
win = scipy.signal.get_window('hanning',nperseg,fftbins=False)