让我们假设我们有一个数据集,它可以近似地给出
import numpy as np
x = np.linspace(0,2*np.pi,100)
y = np.sin(x) + np.random.random(100) * 0.2
因此,我们有 20% 的数据集变化。我的第一个想法是使用 scipy 的 UnivariateSpline 函数,但问题是这并没有很好地考虑小噪声。如果您考虑频率,则背景比信号小得多,因此仅使用样条曲线可能是一个想法,但这将涉及来回傅立叶变换,这可能会导致不良行为。 另一种方法是移动平均线,但这也需要正确选择延迟。
任何提示/书籍或链接如何解决这个问题?
最佳答案
我更喜欢 Savitzky-Golay filter .它使用最小二乘法将数据的一个小窗口回归到多项式上,然后使用多项式来估计窗口中心的点。最后窗口向前移动一个数据点并重复该过程。这一直持续到每个点都相对于其邻居进行了最佳调整。即使处理来自非周期性和非线性源的噪声样本,它也能很好地工作。
这里是 thorough cookbook example .请参阅下面的代码以了解它的易用性。注意:我省略了定义 savitzky_golay()
函数的代码,因为您可以从我上面链接的食谱示例中复制/粘贴它。
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,2*np.pi,100)
y = np.sin(x) + np.random.random(100) * 0.2
yhat = savitzky_golay(y, 51, 3) # window size 51, polynomial order 3
plt.plot(x,y)
plt.plot(x,yhat, color='red')
plt.show()
更新:我注意到我链接到的食谱示例已被删除。幸运的是,Savitzky-Golay 过滤器已被纳入 into the SciPy library ,正如 @dodohjk 所指出的那样(感谢 @bicarlsen 更新链接)。 要使用 SciPy 源修改上述代码,请键入:
from scipy.signal import savgol_filter
yhat = savgol_filter(y, 51, 3) # window size 51, polynomial order 3
https://stackoverflow.com/questions/20618804/