首页 > 解决方案 > Accelerate 和 NumPy 对 FFT 产生不同的结果

问题描述

我正在为 CoreML 开发一个特征工程管道,我需要对我的数据执行 FFT。问题在于 Accelerate 框架的结果和 NumPy FFT 的结果不同。

迅速:

public func fft(_ input: [Double]) -> [Double] {
    var real = [Double](input)
    var imaginary = [Double](repeating: 0.0, count: input.count)
    var splitComplex = DSPDoubleSplitComplex(realp: &real, imagp: &imaginary)

    let length = vDSP_Length(floor(log2(Float(input.count))))
    let radix = FFTRadix(kFFTRadix2)
    let weights = vDSP_create_fftsetupD(length, radix)
    vDSP_fft_zipD(weights!, &splitComplex, 1, length, FFTDirection(FFT_FORWARD))

    var magnitudes = [Double](repeating: 0.0, count: input.count)
    vDSP_zvmagsD(&splitComplex, 1, &magnitudes, 1, vDSP_Length(input.count))

    var normalizedMagnitudes = [Double](repeating: 0.0, count: input.count)
    vDSP_vsmulD(sqrt(magnitudes), 1, [2.0 / Double(input.count)], &normalizedMagnitudes, 1, vDSP_Length(input.count))

    vDSP_destroy_fftsetupD(weights)

    return normalizedMagnitudes
}

Python:

def fft(series: pd.Series):
    f = np.fft.fft(series)
    fa = np.abs(f)
    return pd.Series(fa)

我对每种方法都使用相同的 100 个值。

我想这与规范化部分有关,但我什至不确定两个数组是否包含相同的内容,例如:

我只对积极的幅度感兴趣。

编辑:

这是 NumPy 图:

数字货币

这是加速情节:

加速

我希望有人能帮帮忙 :)

标签: pythonswiftnumpyfftcoreml

解决方案


有两个问题:

  • 正如E.Coms所指出的,使用 Accelerate 框架的 FFT 的实现包括一个标准化步骤,该步骤采用幅度的平方根并乘以标量2/N。使用 NumPy 的实现没有。

  • NumPy 的 FFT 支持任意长度的输入,并且生成的频率箱如您所料(索引 0 处的零频率,索引 1-50 处的正频率和索引 51-99 处的负频率)。另一方面,Accelerate 框架中的 FFT 需要具有 2 的幂的长度。相应地,该代码示例计算前 64 个输入值的 FFT。这将零频率置于索引 0,正频率置于索引 1-32,负频率置于索引 33-63。剩余的索引 (64-99) 只是剩余的未触及输入。


推荐阅读