为啥 scipy 和 numpy fft 图看起来不同?

Posted

技术标签:

【中文标题】为啥 scipy 和 numpy fft 图看起来不同?【英文标题】:Why do scipy and numpy fft plots look different?为什么 scipy 和 numpy fft 图看起来不同? 【发布时间】:2018-04-28 16:55:04 【问题描述】:

我目前正在为一门课程做一些频谱分析,尽管我们还没有明确地教过傅里叶变换。我一直在使用 scipy 和 numpy 中的各种 fft 算法来处理一些我知道答案应该是什么样子的数据

在这种情况下,它是一个 8kHz 载波频率的 AM 信号,顶部是 1kHz 调制正弦波,因此 fft 上应该有 3 个清晰的峰值

当应用scipy.fftpack.rfftnumpy.fft.rfft 时,我分别得到以下图:

Scipy:

Numpy:

虽然 2 个 FFT 的形状与峰值之间的正确比率大致相同,但 numpy 的一个看起来更平滑,而 scipy 的最大峰值稍小,并且噪声更大。

我假设这在很大程度上取决于离散傅立叶变换算法的不同应用,并且已经看到其他关于 scipy 实现如何在运行时更快的文章。但是我一直在徘徊,具体是什么导致了这种差异,哪一个实际上更准确?

编辑:用于生成图的代码:

data = pd.read_csv("./Waveforms/AM waveform Sine.csv", sep = ',', dtype = float)

data = data.as_matrix()
time = data[:,0]
voltage = data[:,1]/data[:,1].max() # normalise the values

#scipy plot:
plt.figure()
magnitude =  scipy.fftpack.rfft(voltage)
freq = scipy.fftpack.rfftfreq(len(time),np.diff(time)[0])
plt.figure()
plt.plot(freq, np.absolute(magnitude), lw = 1)
plt.ylim(0,2500)
plt.xlim(0,15)

#numpy plot
magnitude = np.fft.rfft(voltage)
freq = np.fft.rfftfreq(len(time),np.diff(time)[0])

plt.figure()
plt.plot(freq, np.absolute(magnitude), lw = 1)
plt.ylim(0,2500)
plt.xlim(0,15)

【问题讨论】:

【参考方案1】:

来自 NumPy 的rfft 文档:

返回:

out : 复杂的 ndarray

截断或补零的输入,沿轴转换 由轴表示,如果未指定轴,则为最后一个。如果 n 是 甚至,变换轴的长度为 (n/2)+1。如果 n 是奇数,则 长度为 (n+1)/2。

没有明确写出来,但“转换后的数据”在这里很复杂。

来自 rfft 的 SciPy 文档

z : 真正的 ndarray

返回的实数数组包含:

[y(0),Re(y(1)),Im(y(1)),...,Re(y(n/2))]              if n is even
[y(0),Re(y(1)),Im(y(1)),...,Re(y(n/2)),Im(y(n/2))]   if n is odd

结论:存储不同。

首先,查看magnitude 的长度,这两种情况都会有所不同。为了清楚起见,我在下面举一个例子:

In [33]: data = np.random.random(size=8)

In [34]: np.fft.rfft(data)
Out[34]: 
array([ 3.33822983+0.j        ,  0.15879369+0.48542266j,
        0.00614876+0.03590621j, -0.67376592-0.69793372j,  1.51730861+0.j        ])

In [35]: scipy.fftpack.rfft(data)
Out[35]: 
array([ 3.33822983,  0.15879369,  0.48542266,  0.00614876,  0.03590621,
       -0.67376592, -0.69793372,  1.51730861])

这两种情况的第一个元素是所谓的“直流分量”(信号的平均值)。

然后,您可以在 SciPy 版本中识别 NumPy 版本的实部和虚部的连续性。

【讨论】:

不同的存储实现如何导致不同形状的图?从您的示例的外观来看,完全相同的数据以数字形式存储,只是格式不同? 将复数值存储在数组的连续元素中意味着np.absolute 对数组magnitude 的操作将在np.fft.rfft 的情况下给出复数值的范数(即相关物理量)而对于scipy.fftpack.rfft的情况,它会先给出数字的实部的绝对值,然后再给出复分量的大小,这两种运算的结果是不同的。

以上是关于为啥 scipy 和 numpy fft 图看起来不同?的主要内容,如果未能解决你的问题,请参考以下文章

numpy.fft 和 scipy.fftpack 有啥区别?

numpy 的 QR 看起来比 scipy 的快 - 为啥?

Matlab 中的 FFT 和 numpy / scipy 给出不同的结果

Scipy FFT 和 Numpy FFT 在脉冲序列频谱上存在分歧?

Matlab fft 和 Scipy fft 的 FFT 结果略有不同

为啥不使用 Scipy 的 FFT 代码中的结果与 Scipy FFT 不相似?