如果我的数据是1 / f噪声,如何从功率谱密度中确定?

时间:2017-02-28 14:15:48

标签: python numpy signal-processing fft frequency-analysis

假设您有以下一系列值:

import numpy as np
data1=np.array([1,  0.28571429,  0.20408163,  0.16326531,  0.14285714,
        0.10204082,  0.08163265,  0.06122449,  0.04081633,  0.02040816])

您现在想使用data1绘制numpy.fft的{​​{3}}:

ps1 = np.abs(np.fft.fft(data1))**2
time_step = 1 / 30
freqs1 = np.fft.fftfreq(data1.size, time_step)
idx1 = np.argsort(freqs1)
fig,ax=plt.subplots()
ax.plot(freqs1[idx1], ps1[idx1],color='red',label='data1')
plt.grid(True, which="both")
ax.set_yscale('log')
ax.set_xscale('log')
plt.xlabel("Frequency")
plt.ylabel("Power")
plt.xlim(0,15)

Spectral Density

我的问题:如果图表代表我的系列的信号,我如何从功率谱密度确定这是1/f (或任何其他)噪音

1 个答案:

答案 0 :(得分:2)

  

如果我看一下图像,我很想得出结论,这个系列就像是一个幂律行为,但要说明你需要证明它有1 / f噪声。

让我们看看我们是否可以验证这个假设:

  1. 为1 / f噪声构建噪声模型:scale / (1 + f ** alpha)。这是1 / f niose的数学模型,参数scale(振幅)和alpha(描述高频与低频的比率)

  2. 将噪声模型拟合到数据中(在这种情况下使其与功率谱密度相符)

  3. 检查结果。这个模型看起来好像描述了数据吗?如果不是 - 试着找一个不同的模型。但要注意overfitting

  4. 剪断:

    from scipy.optimize import curve_fit
    import numpy as np
    import matplotlib.pyplot as plt
    
    
    data1 = np.array([1,  0.28571429,  0.20408163,  0.16326531,  0.14285714,
                      0.10204082,  0.08163265,  0.06122449,  0.04081633,  0.02040816])
    
    
    def one_over_f(f, alpha, scale):
        return scale / f ** alpha    
    
    
    time_step = 1 / 30
    ps1 = np.abs(np.fft.fft(data1)) ** 2
    freqs1 = np.fft.fftfreq(data1.size, time_step)
    
    # remove the DC bin because 1/f cannot fit at 0 Hz
    ps1 = ps1[freqs1 != 0]
    freqs1 = freqs1[freqs1 != 0]
    
    params, _ = curve_fit(one_over_f, np.abs(freqs1), ps1)
    ps2 = one_over_f(freqs1, *params)
    
    idx1 = np.argsort(freqs1)
    
    fig, ax = plt.subplots()
    ax.plot(freqs1[idx1], ps1[idx1], color='red', label='data1')
    ax.plot(freqs1[idx1], ps2[idx1], color='blue', label='fit')
    plt.grid(True, which="both")
    ax.set_yscale('log')
    ax.set_xscale('log')
    plt.xlabel("Frequency")
    plt.ylabel("Power")
    plt.xlim(0,15)
    plt.legend()
    
    print('Alpha:', params[0], '\nScale:', params[1])
    

    enter image description here

    从视觉上看,该模型看起来非常适合1 / f光谱。这不是证据。很难证明数据具有一定的分布。但是,如果选择的噪声模型在视觉上符合您的需求足够好的数据,您就可以自己判断。