4

一連のデータに対して堅牢な移動スケール推定値を計算するための高速で効率的な方法を探しています。私は、通常 3 ~ 400k 要素の 1 次元配列を使用しています。最近まで、シミュレートされたデータ (壊滅的な外れ値なし) を扱っていましたが、優れた Bottleneck パッケージの move_std 関数が役に立ちました。ただし、ノイズの多いデータに移行したため、std の動作が適切ではなくなりました。

過去に、私は非常に単純なバイウェイト中間分散コードを要素ごとに使用して、動作の悪い分布の問題に対処しました。

def bwmv(data_array):
    cent = np.median(data_array)
    MAD = np.median(np.abs(data_array-cent))
    u = (data_array-cent) / 9. / MAD
    uu = u*u
    I = np.asarray((uu <= 1.), dtype=int)
    return np.sqrt(len(data_array) * np.sum((data_array-cent)**2 * (1.-uu)**4 * I)\
            /(np.sum((1.-uu) * (1.-5*uu) * I)**2))

ただし、現在使用している配列は十分に大きいため、非常に遅くなります。そのような推定器を提供するパッケージを知っている人はいますか、またはこれに迅速かつ効率的な方法でアプローチする方法についての推奨事項はありますか?

4

1 に答える 1

3

同様の状況で単純なローパス フィルターを使用しました。

概念的には、 を使用して平均の移動推定を取得できますfac = 0.99; filtered[k] = fac*filtered[k-1] + (1-fac)*data[k]。これは (C で) 実装するのが非常に効率的です。これより少し派手な IIR フィルターであるバターワース ローパスは、scipy で簡単にセットアップできます。

b, a = scipy.signal.butter(2, 0.1)
filtered = scipy.signal.lfilter(b, a, data)

「スケール」の推定値を取得するには、この「平均推定値」をデータから差し引くことができます。これにより、実際にローパスがハイパス フィルターに変わります。その abs() を取得し、別のローパス フィルターに通します。

結果は次のようになります。

スクリプト出力

完全なスクリプト:

from pylab import *
from scipy.signal import lfilter, butter

data = randn(1000)
data[300:] += 1.0
data[600:] *= 3.0
b, a = butter(2, 0.03)
mean_estimate = lfilter(b, a, data)
scale_estimate = lfilter(b, a, abs(data-mean_estimate))

plot(data, '.')
plot(mean_estimate)
plot(mean_estimate + scale_estimate, color='k')
plot(mean_estimate - scale_estimate, color='k')

show()

明らかに、butter() パラメータは問題に合わせて調整する必要があります。次数を 2 ではなく 1 に設定すると、最初に説明した単純なフィルターが正確に得られます。

免責事項: これは問題に対するエンジニアの見解です。このアプローチは、統計的または数学的な方法でおそらく適切ではありません。また、それがあなたの問題を本当に解決するかどうかはわかりません (解決しない場合はもっと詳しく説明してください) が、心配しないでください。

于 2013-04-14T18:21:09.497 に答える