假设您有以下一系列值:
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)
我的问题:如果图表代表我的系列的信号,我如何从功率谱密度确定这是1/f
(或任何其他)噪音?
答案 0 :(得分:2)
如果我看一下图像,我很想得出结论,这个系列就像是一个幂律行为,但要说明你需要证明它有1 / f噪声。
让我们看看我们是否可以验证这个假设:
为1 / f噪声构建噪声模型:scale / (1 + f ** alpha)
。这是1 / f niose的数学模型,参数scale
(振幅)和alpha
(描述高频与低频的比率)
将噪声模型拟合到数据中(在这种情况下使其与功率谱密度相符)
检查结果。这个模型看起来好像描述了数据吗?如果不是 - 试着找一个不同的模型。但要注意overfitting!
剪断:
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])
从视觉上看,该模型看起来非常适合1 / f光谱。这不是证据。很难证明数据具有一定的分布。但是,如果选择的噪声模型在视觉上符合您的需求足够好的数据,您就可以自己判断。