web-dev-qa-db-ja.com

統計的中央値、モード、歪度、尖度を推定するための「オンライン」(反復子)アルゴリズム?

値のセットの中央値、モード、歪度、尖度を推定するアルゴリズムはありますが、すべての値を一度にメモリに保存する必要はありませんか?

基本的な統計を計算したい:

  • 平均:算術平均
  • 分散:平均からの偏差の二乗の平均
  • 標準偏差:分散の平方根
  • 中央値:数値の大きい半分と小さい半分を分離する値
  • モード:セットで見つかった最も頻繁な値
  • 歪度:tl;博士
  • 尖度:tl;博士

これらのいずれかを計算するための基本的な式は、学年の算術です。それらを実装する多くの統計ライブラリもあります。

私の問題は、処理しているセット内の多数の値(10億)です。Pythonで作業している場合、リストやハッシュを数十億の要素で作成することはできません。これをCで書いたとしても、10億要素の配列はあまり実用的ではありません。

データはソートされません。他のプロセスによって、オンザフライでランダムに生成されます。各セットのサイズは非常に可変であり、サイズは事前にわかりません。

セット内の各値を任意の順序で繰り返し、平均と分散をうまく処理する方法を既に理解しています。 (実際、私の場合、生成された順番にそれらを取得します。)これは、使用しているアルゴリズムです、礼儀 http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On- line_algorithm

  • 3つの変数を初期化する:count、sum、およびsum_of_squares
  • 各値に対して:
    • 増分カウント。
    • 合計する値を追加します。
    • 値の2乗をsum_of_squaresに追加します。
  • 変数の平均として保存して、合計をカウントで除算します。
  • Sum_of_squaresをカウントで除算し、変数mean_of_squaresとして保存します。
  • 二乗平均、square_of_meanとして保存。
  • Mean_of_squaresからsquare_of_meanを減算し、分散として保存します。
  • 出力の平均と分散。

この「オンライン」アルゴリズムには弱点があります(例:sum_of_squaresが整数範囲または浮動小数点精度よりも急速に大きくなるための精度の問題)が、基本的に各セットにすべての値を保存することなく必要なものを提供します。

しかし、追加の統計(中央値、モード、歪度、尖度)を推定するための同様の手法が存在するかどうかはわかりません。 N値を処理するために必要なメモリがO(N)を大幅に下回っている限り、偏った推定器、またはある程度精度を低下させる方法でさえも生きることができます。

ライブラリにこれらの操作の1つ以上を「オンライン」で計算する機能がある場合は、既存の統計ライブラリを指定することも役立ちます。

83
Ryan B. Lynch

スキューネスと尖度

(分散の線に沿った)歪度と尖度のオンラインアルゴリズムについては、同じwikiページを参照してください here 高モーメント統計の並列アルゴリズム。

中央値

ソートされたデータがないと中央値は厳しいです。知っているなら、あなたが持っているデータポイントの数、理論的には部分的にソートするだけで良い、例えば 選択アルゴリズム を使用します。しかし、それは何十億もの価値がある場合でもあまり役に立ちません。頻度カウントを使用することをお勧めします。次のセクションを参照してください。

周波数カウント付きの中央値とモード

整数の場合、 frequencies をカウントします。おそらく、関連性がなくなったと確信できる値を超えて最高値と最低値を切り捨てるでしょう。フロート(または整数が多すぎる)の場合、おそらくバケット/インターバルを作成し、整数の場合と同じアプローチを使用します。 (概算)モードと中央値の計算は、頻度表に基づいて簡単になります。

正規分布確率変数

正規分布している場合は、母集団サンプル 平均分散歪度 、および 尖度 を最大値として使用します小さなサブセットの尤度推定量。それらを計算するための(オンライン)アルゴリズム、あなたはすでにあなたです。例えば。推定誤差が十分小さくなるまで、数十万または数百万のデータポイントを読み取ります。セットからランダムに選択することを確認してください(たとえば、最初の100'000値を選択することでバイアスを導入しないでください)。同じアプローチは、通常の場合のモードと中央値の推定にも使用できます(両方のサンプル平均が推定量であるため)。

さらなるコメント

これが役立つ場合は、上記のすべてのアルゴリズムを並行して実行できます(多くの並べ替えおよび選択アルゴリズム(QuickSortやQuickSelectなど)を含む)。

既知の分布が与えられた場合の理論モーメントの推定量ではなく、サンプルモーメント、中央値、およびモードについて説明することを常に仮定しました(正規分布のセクションを除く)。

一般的に、すべての観測値が同じランダム変数(同じ分布を持つ)とモーメント、モード、この分布の中央値は実際に存在します。最後の警告は無害ではありません。たとえば、 Cauchy Distribution の平均(およびすべてのより高いモーメント)は存在しません。この場合、「小さな」サブセットのサンプル平均は、サンプル全体のサンプル平均から大きく外れている可能性があります。

51
stephan

これらの増分/再帰平均および中央値推定器を使用します。どちらも定数ストレージを使用します。

mean += eta * (sample - mean)
median += eta * sgn(sample - median)

ここで、etaは小さな学習率パラメーター(例えば0.001)、sgn()は{のいずれかを返すsignum関数です-1、0、1}。 (データが非定常であり、時間の経過に伴う変化を追跡する場合は、定数etaを使用します。そうでない場合、定常ソースの場合はのようなものを使用できます平均推定量のeta= 1/n。ここで、nはこれまでに見られたサンプルの数です...残念ながら、これは中央推定量では機能しないようです。)

このタイプの増分平均推定器は、至る所で使用されているようです。教師なしニューラルネットワークの学習ルールではありますが、利点(外れ値に対する堅牢性)にもかかわらず、中央値バージョンはあまり一般的ではないようです。中央値バージョンは、多くのアプリケーションで平均推定量の代替として使用できるようです。

私は同様の形式のインクリメンタルモード推定器を見てみたいです...

[〜#〜] update [〜#〜]

増分中央値推定器を変更して、任意の分位数を推定しました。一般的に、分位数関数( http://en.wikipedia.org/wiki/Quantile_function )は、データを2つの小数部(pと1-p)に分割する値を示します。以下は、この値を増分的に推定します。

quantile += eta * (sgn(sample - quantile) + 2.0 * p - 1.0)

値pは[0,1]以内でなければなりません。これは本質的にsgn()関数の対称出力{-1,0,1}を片側に傾け、データサンプルを2つの不均等なサイズのビン(フラクションpおよびデータの1-pは、それぞれ分位推定値よりも小さい/大きい)。 p = 0.5の場合、これは推定値の中央値に減少することに注意してください。

53
Tyler Streeter

観測値を保存せずに分位点とヒストグラムの動的計算のためのP-Squareアルゴリズム を実装しましたPython私が書いたモジュールは LiveStats です。ライブラリは、モードを除くすべての統計情報をサポートしますが、モード推定の満足のいく解決策はまだ見つかりません。

10
Sean

ライアン、私はあなたが平均と分散を正しくしていないのではないかと心配しています...これは数週間前に現れました here 。そして、オンラインバージョンの強みの1つ(実際にはウェルフォードの方法の名前になります)は、それが特に正確で安定しているという事実です。議論を参照してください here 。強みの1つは、総和または総平方和を保存する必要がないという事実です...

モードと中央値に対するオンラインアプローチは考えられません。リスト全体を一度に検討する必要があります。しかし、分散と平均のアプローチと同様のアプローチが歪度と尖度にも有効である可能性が非常に高いかもしれません...

7
Jaime

質問で引用されたウィキペディアの記事には、歪度と尖度をオンラインで計算するための公式が含まれています。

モードの場合-私は信じています-これをオンラインで行う方法はありません。どうして?前の値を複製する最後の値以外に、入力のすべての値が異なると仮定します。この場合、最後の値が前に表示された値を複製し、それが最も頻繁な値になることを検出するために、入力に表示されたすべての値を覚えておく必要があります。

中央値についてはほぼ同じです。最後の入力までは、すべての入力値が現在の中央値の前後にある可能性があるため、すべての入力値が異なる場合、どの値が中央値になるかわかりません。入力の長さを知っている場合、すべての値をメモリに保存せずに中央値を見つけることができますが、入力シーケンスが間違っていると中央値が大きくシフトする可能性があるため、多くの値を保存する必要があります後半は、前半の中央値から任意の値を作成する可能性があります。

(正確な計算のみを参照していることに注意してください。)

3

数十億のデータポイントがある場合、厳密な回答ではなく、正確な回答が必要になることはほとんどありません。一般に、数十億のデータポイントがある場合、それらを生成する基礎となるプロセスは、何らかの統計的な定常性/エルゴシティ/混合特性に従います。また、分布が合理的に連続的であると期待するかどうかも重要です。

これらの状況では、オンライン、低メモリ、estimation分位数(中央値は0.5分位の特殊なケース)のアルゴリズムもあります。正確な答えが必要ない場合はモードとして。これは、統計のアクティブなフィールドです。

分位推定の例: http://www.computer.org/portal/web/csdl/doi/10.1109/WSC.2006.323014

モード推定の例:Bickel DR。連続データのモードと歪度の堅牢な推定量。計算統計とデータ分析。 2002; 39:153–163。土井:10.1016/S0167-9473(01)00057-3.

これらは、計算統計のアクティブなフィールドです。最適なアルゴリズムは1つだけではなく、それらの多様性(実際には統計的推定量)があり、さまざまな特性、仮定、および性能を持つ分野に参入しています。それは実験的な数学です。おそらく数百から数千の主題に関する論文があります。

最後の質問は、実際に歪度と尖度を本当に必要とするのか、それとも確率分布を特徴づけるのにより信頼性の高い他のパラメーターが必要なのか(確率分布があると仮定して!)ガウス型を期待していますか?

ほとんどがガウス色になるようにデータをクリーニング/前処理する方法はありますか? (たとえば、対数を取った後の金融取引額はしばしばガウス分布になります)。有限の標準偏差を期待していますか?太った尾を期待していますか?気にする量は、尾の部分ですか、それともバルクですか?

2
Matt Kennel

オンラインでモードを実行することはできないと誰もが言い続けていますが、それは単に真実ではありません。 記事 は、1982年にイェール大学のMichael E. FischerとSteven L. Salzbergによって発明されたまさにこの問題を行うアルゴリズムを説明しています。記事から:

多数決アルゴリズムは、ストリームから単一のアイテムを一時的に保存するためにレジスタの1つを使用します。この項目は、多数要素の現在の候補です。 2番目のレジスタは、0に初期化されたカウンターです。ストリームの各要素について、アルゴリズムに次のルーチンを実行するように依頼します。カウンターの値が0の場合、現在のストリーム要素を新しい多数決候補としてインストールします(既にレジスタにある可能性のある他の要素を置き換えます)。次に、現在の要素が多数決候補に一致する場合、カウンターをインクリメントします。それ以外の場合は、カウンターをデクリメントします。サイクルのこの時点で、これまでに見たストリームの一部に多数決要素がある場合、その要素は候補レジスタにあり、カウンタは0より大きい値を保持します。多数決要素がない場合はどうなりますか?ストリーム環境では不可能なデータの2回目の通過を行わない限り、アルゴリズムはこの状況で常に明確な答えを出すことはできません。多数決要素がある場合は、それを正しく識別することを単に約束するだけです。

より多くのメモリを備えた上位Nを見つけるために拡張することもできますが、これはモードでそれを解決するはずです。

2
hackartist

最終的に、分布のアプリオリなパラメトリック知識がない場合、すべての値を保存する必要があると思います。

それは、ある種の病理学的状況を扱っていない限り、治療薬(Rousseuw and Bassett 1990)があなたの目的には十分かもしれないということです。

非常に簡単に言うと、中央値のバッチの中央値を計算します。

1
Edward Grace

この問題は、Pebayなどによって解決されました。

https://prod-ng.sandia.gov/techlib-noauth/access-control.cgi/2008/086212.pdf

0
user14717

中央とモードは、利用可能な一定のスペースのみを使用してオンラインで計算することはできません。ただし、中央値とモードはとにかく「定量的」よりも「記述的」であるため、それらを推定できます。データセットをサンプリングすることにより。

データが長期的に正規分布している場合は、平均値を使用して中央値を推定できます。

次の手法を使用して中央値を推定することもできます。データストリームの1,000,000エントリごとに中央推定値M [i]を確立し、M [0]が最初の100万エントリの中央値、M [1] 2番目の100万エントリの中央値など。次に、中央値推定器としてM [0] ... M [k]の中央値を使用します。もちろんこれはスペースを節約します。パラメーター1,000,000を「調整」することで、スペースの使用量を制御できます。これは再帰的に一般化することもできます。

0
Antti Huima

OK、これらを試してください:

c ++の場合:

double skew(double* v, unsigned long n){
    double sigma = pow(svar(v, n), 0.5);
    double mu = avg(v, n);

    double* t;
    t = new double[n];

    for(unsigned long i = 0; i < n; ++i){
        t[i] = pow((v[i] - mu)/sigma, 3);
    }

    double ret = avg(t, n);

    delete [] t;
    return ret;
}

double kurt(double* v, double n){
    double sigma = pow(svar(v, n), 0.5);
    double mu = avg(v, n);

    double* t;
    t = new double[n];

    for(unsigned long i = 0; i < n; ++i){
        t[i] = pow( ((v[i] - mu[i]) / sigma) , 4) - 3;
    }

    double ret = avg(t, n);

    delete [] t;
    return ret;
}

サンプルの分散(svar)と平均(avg)を既に計算できると言う場合、そのためにそれらを関数にポイントします。

また、ピアソンの近似値もご覧ください。このような大規模なデータセットでは、かなり似ています。 3(平均-中央値)/中央値が最大の標準偏差-最小/ 2

フロートモードには意味がありません。通常、それらを有効なサイズ(1/100 *(最大-最小)など)のビンに固定します。

0
peter