Accelerate和NumPy产生不同的FFT结果

时间:2019-03-11 23:30:25

标签: python swift numpy fft coreml

我正在为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个值。

我猜想它与规范化部分有关,但是我什至不确定两个数组是否包含相同的东西:

  • 索引0:零频率项
  • 指数1-50:正值
  • 指数50-99:负值

我只对正值感兴趣。

编辑:

这是NumPy图:

NumPy

这是加速图:

Accelerate

我希望有人能提供帮助:)

1 个答案:

答案 0 :(得分:2)

有两个问题:

    {li>

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

  • NumPy的FFT支持任意长度的输入,并且产生的频率仓符合您的期望(索引0处为零频率,索引1-50处为正频率,索引51-99处为负频率)。另一方面,加速框架中的FFT的长度必须是2的幂。相应地,该代码示例将计算您的前64个输入值的FFT。这会将零频率设为索引0,将正频率设为索引1-32,将负频率设为索引33-63。其余的索引(64-99)只是剩下的未修改的输入。