限られたメモリでのオンラインの分散推定


7

時間内に発生するイベントに関連するメトリックの平均と分散を計算することを目的とするコンポーネントを作成していますが、内部メモリは限られています。

イベントがショップに入場する訪問者であり、メトリックが年齢であると想像してください。

期間中、私のコンポーネントは各訪問者の年齢のイベントを受け取ります。コンポーネントに各年齢の履歴を記憶させたくありません。理想的には、平均A、分散V、およびイベント数のみを格納するライトコンポーネントが欲しいNです。

ageのある各イベントの後にE、これらの3つの値を更新します。

N<=N+1
A<=(A*N+E)/(N+1)
V<=???

何のためにV?私は次のようなものを考えています:

V<=(V*N+(E-A)^2)/(N+1)

私の以前の人Vは古いAものを使用しているため、正確ではないことを知っています。これは平均ではありません。

Q1-正確な式はありますか?
Q2-そうでない場合、私の提案は適切な見積もりですか?偏っていますか?N増加すると、正しく収束しますか?
Q3-より良い式はありますか?


数値の精度も問題になる可能性があります。また、崩壊を伴う分散を計算するオンラインアルゴリズムも参照してください。
Scortchi-モニカを回復

E ^ 2の合計も保持できますか?
アンディW

はい、大丈夫でしょう。私は、有限個の値を保つが、N.に依存することはできません
アルノーMégret

4
たとえばcs.yale.edu/publications/techreports/tr222.pdfのセクション1で提供されているように、数値的に安定した1パス分散更新アルゴリズムを使用します。Andy W.の答えは恐ろしい方法で、非常に不正確な場合があります。
マークL.ストーン

回答:


10

オンラインで分散を計算するための素晴らしく単純なアルゴリズムは、Welford(1962)によって記述されました。以下に、オフラインで動作するC ++ / Rcppの実装を示しますが、オンラインシナリオに簡単に適応できます。

List welford_cpp(NumericVector x) {

  int n = x.length();
  double delta;
  double msq = 0;
  double mean = x[0];

  if (n > 1) {
    for (int i = 1; i < n; i++) { 
      delta = x[i] - mean;
      mean += delta / (i+1);
      msq += delta * (x[i] - mean);
    }
    return Rcpp::List::create(Rcpp::Named("mean") = mean,
                              Rcpp::Named("variance") = msq / (n-1));
  }

  return Rcpp::List::create(Rcpp::Named("mean") = mean,
                            Rcpp::Named("variance") = NAN);
}

ご覧のとおり、必要なのは、、、、およびの4つの変数を保存するだけndelta、平均と分散を同時に計算できます。msqmean


ウェルフォード、BP(1962)。二乗と積の修正合計を計算する方法についての注意。テクノメトリクス4(3):419-420。


とても素敵です、ありがとうございました(マークストーンも参考にしてください)。私の答えを削除します。
アンディW

1

分散は、すべての値と平均値との差の2乗に比例するか、または(stats.SEに記載されている多くのスレッドと同じように、この回答が別の質問に書いたように)2乗に比例するように表すこともできますすべてのサンプル間のペアワイズ差。

だから私たちは知っています:

Var(x)=1ni(XiX¯)2=12n2i,j(XiXj)2

最後のインデックスとしてインデックス付けされた別のサンプルを追加するとします。以前の分散は次のようになります。k

Varold(x)=12(n1)2i<k,j<k(XiXj)2

あなたの新しい分散は

Varnew(x)=12n2i,j(XiXj)2=12n2(i<k,j<k(XiXj)2+j<k(XkXj)2+i<k(XiXk)2)

だが

j<k(XkXj)2=i<k(XiXk)2i<k,j<k(XiXj)2=2(n1)2Varold(x)

そう

Varnew(x)=(n1n)2Varold(x)+1n2j<k(XkXj)2

@ MarkL.Stoneがコメントで述べたように、すべての保持する必要があるため、これはまだ効率的ではありません。それでは、式を拡張して、より扱いやすいものに到達しましょう。Xi

12Σj<kバツkバツj2=12Σj<kバツk22バツjバツk+バツj2=12Σj<kバツk22バツkΣj<kバツj+Σj<kバツj2=12kバツk22バツkk1バツold¯+k1バツold2¯
ため
Σj<kバツj=k1バツold¯Σj<kバツj2=k1バツold2¯

最終的な形は

Varewバツ=12Varoldバツ+12kバツk22バツkk1バツold¯+k1バツold2¯

この式を使用すると、メモリごとに分散を効果的に更新できます。また、シングルポイント更新の代わりにバッチを使用するように補完することもできます。

基本的に、平均、2乗されたサンプルの平均、および反復ごとの分散を保存し、それを使用して分散式を更新する必要があります。


さらに

バツold2¯=Varoldバツ+バツold¯2Varewバツ=12Varoldバツ+12kバツk22バツkk1バツold¯+k1Varoldバツ+バツold¯2

これにより、保存する必要のある数量が2に減ります。


この方法では、更新を計算するために以前のすべてのデータポイントの可用性が必要ではありませんか?もしそうなら、それは限られたメモリを扱うという考えに反しています。@Timによる回答のウェルフォードの線に沿ったオンライン更新アルゴリズムは、cs.yale.edu / publications / techreports / tr222.pdfで説明されている同様のアルゴリズムのクラスの特定のインスタンスであり、古いものを保存する必要がないことに注意してください。データポイント。ただし、古い情報を保持するための2つのレジスタ(スカラー変数)のみ。
マークL.ストーン

@ MarkL.Stoneうーん。はい、これには以前のすべての値が必要です。そうです。バツ
Firebug 2016

@ MarkL.Stone 3つのスカラーを格納する必要があるように、式を更新しました。私はそれがさらに削減され、おそらく他のソリューションと同等であることができることをすでに確認しています。
Firebug 2016

減算により、負でない量のみを追加するのではなく、改訂されたアルゴリズムは、ウェルフォードおよび類似のアルゴリズムよりも数値的に正確ではありません(ロバスト)。そこには何のメリットも見当たりません。
マークL.ストーン

0

OKアンディWが答えました。平均をE平均と同じ方法で保存することで、を使用できます。E2V=eバツpE2eバツpE2


2
あなたはおそらく意味ですか期待値の?(そして指数関数ではありません。)eバツpE2E2
Andy W

8
あなたが正しい答えを得ることを気にしない限り、その方法は問題ありません。
マークL.ストーン

2
数値の不安定性、したがって数値の不正確さ。正確な算術、つまり無限の精度で実行される場合、それは正しいです。コンピュータ上の有限精度で..それは非常に不正確になることができ、さらには負の出てくる(そして実際に多くの場面で持っている)ことができます
マーク・L・ストーン

4
Excelは実際にこの方法を長い間使用していました(統計学者などからの多くの批判や嘲笑に対して)。非常に単純な状況(平均が大きく、標準偏差が小さいデータ)で、その分散関数に、乱数ジェネレーターの近似に対応する出力を与えることができます(連続する少量だけデータをシフトすると、報告された分散が急激に変化します)。これは、違いの壊滅的なキャンセルによって引き起こされました。これらの問題がなぜ重要であるかを示す非常に効果的な方法でした。Excelはそれをしません。
Glen_b-2016

4
この壊滅的なキャンセルについては、たとえば、こちら
Glen_b -Reinstate Monica '15
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.