次のようなデータセットがあると仮定します。
import numpy as np
x = np.linspace(0,2*np.pi,100)
y = np.sin(x) + np.random.random(100) * 0.2
したがって、データセットの 20% に変動があります。私の最初のアイデアは、UnivariateSpline
scipy の機能を使用することでしたが、問題は、これが小さなノイズをうまく考慮していないことです。周波数を考慮すると、バックグラウンドは信号よりもはるかに小さいため、カットオフのみのスプラインがアイデアになるかもしれませんが、それは前後のフーリエ変換を伴うため、動作が悪くなる可能性があります。別の方法は移動平均ですが、これも遅延の適切な選択が必要です。
この問題に対処するためのヒント、本、またはリンクはありますか?
ベストアンサー1
私はサビツキー・ゴレイフィルタ。ここからscipyで入手できます最小二乗法を使用して、データの小さなウィンドウを多項式に回帰し、多項式を使用してウィンドウの中心のポイントを推定します。最後に、ウィンドウが 1 つのデータ ポイントだけ前方にシフトされ、プロセスが繰り返されます。これは、すべてのポイントが隣接するポイントに対して最適に調整されるまで続きます。非周期的および非線形ソースからのノイズの多いサンプルでもうまく機能します。
がここにあります徹底的な料理本の例ただし、これは現在では古くなっています。注: 関数を定義するコードは、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フィルタが組み込まれました。SciPyライブラリに、指摘したように翻訳:(ありがとうビカールセン更新されたリンクについては、こちらを参照してください。上記のコードを SciPy ソースを使用して修正するには、次のように入力します。
from scipy.signal import savgol_filter
yhat = savgol_filter(y, 51, 3) # window size 51, polynomial order 3