【问题标题】:Differences between MATLAB and Numpy/Scipy FFTMATLAB 和 Numpy/Scipy FFT 的区别
【发布时间】:2020-10-23 11:17:55
【问题描述】:

编辑: 事实证明,这仍然是一个浮点舍入误差的问题,就像其他问题一样。 fft 与 ifft 绝对误差的不对称性来自数字大小的差异(1e10 与 1e8)。


所以有很多关于 Numpy/Scipy 和 MATLAB FFT 的区别的问题;然而,其中大部分归结为浮点舍入错误以及 MATLAB 会将 1e-15 顺序的元素变成真正的 0 的事实,这不是我所追求的。

我看到了一个完全不同的问题,对于相同的输入,Numpy/Scipy FFT 会产生来自 MATLAB 的 1e-6 量级的差异。同时对于相同的输入,Numpy/Scipy IFFT 会在订单或 1e-9 上产生差异。我的数据是长度为 2^14 的复杂一维向量,零点位于数组的中间(如果您知道如何分享,请告诉我)。因此,对于这两种语言,我在 fft (ifft) 操作之前和之后都调用 fftshift。

我的问题是这种差异来自哪里,更重要的是,为什么它与 fft 和 ifft 不对称?我可以忍受很小的差异,但是当 1e-6 累积在大量 fft 上时,它就很大了。

对于任何一种语言,fft 的函数形式(我没有对它做任何其他事情)是:

def myfft
    return fftshift(fft(fftshift(myData)))
def myifft
    return fftshift(ifft(fftshift(myData)))

我将数据保存在 .mat 文件中,并使用 scipy.io.loadmat 将其加载到 python 中。数据是一个 (2**14,) numpy 数组

计算 fft 差异并绘制成图

myData = loadmat('mydata.mat',squeeze_me=True)
plt.figure(1)
py = myfft(myData['fft_IN'])
mat = myData['fft_OUT']
plt.plot(py.real-mat.real)
plt.plot(py.imag-mat.imag)
plt.title('FFT Difference')
plt.legend(['real','imaginary'],loc=3)
plt.savefig('fft_diff')

ift 差值是用

计算的
myData = loadmat('mydata.mat',squeeze_me=True)
plt.figure(1)
py = myifft(myData['ifft_IN'])
mat = myData['ifft_OUT']
plt.plot(py.real-mat.real)
plt.plot(py.imag-mat.imag)
plt.title('FFT Difference')
plt.legend(['real','imaginary'],loc=3)
plt.savefig('fft_diff')

版本: 蟒蛇:3.7 MATLAB:R2019a 西比:1.4.1 numpy:1.18.5

【问题讨论】:

  • 绝对差异无关紧要,重要的是相对差异。值 1 相差 1e-16 与 1e10 值相差 1e-6 相同。考虑到数据的长度,FFT 很可能会产生如此大的值。简而言之,您的结果仍然仅因浮点舍入误差而有所不同。
  • @CrisLuengo 如果您想将此作为答案,我会接受。你的评论让我回去看看我正在使用的数据的大小。在 fft 函数中,我按照 1e10 的顺序喂食,在 ifft 中,我正在喂食 1e8。因此,我在绝对误差而不是相对误差方面有所不同是有道理的。
  • 随意发布答案。还有一件事:fft 的输入必须与ifftshift 一起准备。如果数据长度是奇数,这会有所不同。 fftshift 将原点从左侧移到中间,ifftshift 将原点从中间移回左侧。

标签: python matlab numpy scipy fft


【解决方案1】:

你必须想出一个更好的可行的例子来展示你所追求的(我也没有 MATLAB,只有 Octave,可能还有很多其他的)。我运行了 fft 的快速代码并返回,没有任何问题。请注意,通常 DFT (FFT) 使用起来非常微妙。您需要非常仔细地考虑采样、窗口化等。

另外,为什么要与 MATLAB 进行比较,您是否更信任它,或者只是想了解更多关于为什么一个包产生答案而不是另一个包? MATLAB 在后台使用 fftw,它经过了很好的测试和记录,但这并不意味着上述所有细微差别都不会以不同的方式发挥作用。

import numpy as np
import matplotlib.pyplot as plt

fft = np.fft.fft
ifft = np.fft.ifft
def myfft(myData):
    return fft(myData)
def myifft(myData):
    return ifft(myData)

myData = np.exp(-np.linspace(-1, 1, 256)**2 / (2 * .25**2))
plt.figure(1)
fft_python = myifft(myfft(myData))
plt.plot(myData - fft_python.real)
plt.plot(fft_python.imag)
plt.title('FFT Difference')
plt.legend(['real','imaginary'],loc=3)
plt.savefig('fft_diff')

【讨论】:

  • 我信任 MATLAB 数据,因为它已被 Octave、MATLABm 和 Mathematica(学术界)的其他人复制。如果您想看看我的数据是什么样的,我将其托管在:gofile.io/d/S10fcl。这里的问题再次只是浮点舍入错误,但它比以前的问题更加细微。我输入fft的数据是~1e10,ifft是~1e8。因此,预计绝对误差的差异。您必须将 fftshifts 添加到您的 fft 函数中才能准确获得它。
【解决方案2】:

事实证明,这仍然是一个浮点舍入误差问题,就像所有其他 MATLAB 与 numpy fft 问题一样。

对于我的数据,fft 函数的输出具有大约 1e10 的数字。这意味着在这个大小的浮点数上大约 1e-16 的精度是小于或等于 1e-6 的绝对误差。 fft 与 ifft 绝对误差的不对称性来自 ifft 的输出约为 1e8。因此,这个绝对误差将小于或等于 1e-8,这正是我们所看到的。

这要归功于@CrisLuengo,他还很有帮助地指出 fftshift 和 ifftshift 的顺序可以正确处理奇数长度的数组。

【讨论】:

    猜你喜欢
    • 2020-03-28
    • 2012-01-30
    • 2012-10-27
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 2016-08-04
    相关资源
    最近更新 更多