q++

分散の逐次更新

27 Jul 2014

分散をサンプルが増える度に逐次更新したい。

教科書的実装

サンプルがのn個あったとき、そのサンプルの不偏分散は次のようになる。

までの相加平均で次のように算出する。

これをコードに落とし込むことを考えたとき、自然に考えると(2)式を実行して相加平均を得てから、(1)式を実行しそれぞれのサンプルの偏差を求める形になる。これは事前に全サンプルが手元にあり、そこから分散を算出する場合は最速の方法かつ後述するどの方法よりも精度が高い。しかしサンプルが手に入る度に分散を算出したくなった時に、そのたびに相加平均と偏差を出し直さなくてはならず、O(n)の計算量が必要になり、nサンプルまでこれを繰り返すと結果的にO(n^2)の計算量が必要になる。もしサンプルが手に入るたびにしなければならない計算量を定数にできれば、全体の計算量をO(n)に出来る。

単純な変形と問題

逐次計算できるように、それまでのサンプル数に依存しない計算量で行えるような方法を考える。(1)式を展開する。

この結果を素直を利用するならば、前回のサンプルの総和と、前回のサンプルの二乗の総和を持っておけば、新しいサンプルが追加されても、新しいサンプルを加えた総和と、新しいサンプルを加えた後の二乗の総和は定数時間で計算できるため、新しい分散も定数時間で求めることができる。一見これで良さそうに見える。しかしサンプル数が増大したときにこの方式は破綻する。不偏分散はサンプル数には寄らない数値(母集団の分散、母分散)に収束するため、サンプル開始時からずっとその真値は変化しない。しかしカッコの中の式の二つの数値はサンプルが増えるたびに増大していく。このような形式のためサンプル数が増えれば増えるほど、不偏分散はその桁落ち誤差に埋もれていく。これは避けなければならない。

Welfordの方法

桁落ち誤差が発生しないような方式を考える。このような方法にWelfordの方法がある。これは平均と不偏分散を変形したものの漸化式を利用するものだ。まずは相加平均の漸化式を見つける。

次に不偏分散の漸化式を出してみるが、そのままではうまくいかない。を次のようなで置き換える

このの変化量を式変形していくと次のようになる。

は前の漸化式で求まるので、これでの漸化式を得た。不偏分散はを(n-1)で割れば良いので、これで不偏分散の逐次更新ができるようになった。大抵の場合は,,は同じ程度の数値なので、桁落ち誤差が発生するような計算はなくなり、良い精度が期待できる。実際に単純な変形をした二つ目の方法よりもずっと精度が良く、教科書的な実装にそれなりに近い結果になる。

結果

[0,1)の一様乱数に対して、様々なサンプル数で分散を出し、教科書的なベタ実装に対して誤差を出したグラフが以下だ。サンプル数が増えるとWelfordの方法の方がずっと誤差が少ないことがわかる。

welford

その他

参考