巨大な読み取り1回のデータセットの中央値を推定するための優れたアルゴリズムは何ですか?


48

格納するには大きすぎるデータセットの中央値を推定するための優れたアルゴリズム(最小限の計算、最​​小限のストレージ要件を意味する)を探しています。想定できるデータに制限はありません。

精度がわかっている限り、近似は問題ありません。

ポインタはありますか?


4
おそらく、Stackoverflowに問い合わせるとより良い答えが得られるかもしれません。

2
@Srikant:>それは統計の研究でかなり活発な分野です:)ストレージに関して理論的な下限に最も近い解は、かなり巧妙な確率構造も含みます。全体的に見て、私は数か月前に最初にそれを見たときに驚きました。ここには目に見えるよりも多くの統計があります。
user603

回答:


6

各グループの中央値を計算した場合、データセットを非常に小さなデータセット(100または1000または10,000データポイントなど)にグループ化できますか。十分なデータセットでこれを行った場合、十分な小さなデータセットを実行して「平均」ソリューションに収束することにより、各小さなセットの結果の平均やこの結果をプロットできます。


これは興味深いものであり、統計的なアドバイスがいくつかあります。合計で(たとえば)500,000個のiidポイントがあり、(たとえば)1,000個のグループを見て、各グループの中央値を計算すると仮定します。今、私は500の中央値を持っています。これらの500個の中央値に基づいて、中央値全体の信頼区間を計算できる理論はありますか?
PeterR

4
だから、長い間行方不明になった同僚によると、最高の提案はチランジーブ・ブラゴハインとスバシュ・スリのようだ。ストリームの分位点。cs.ucsb.edu/~suri/psdir/ency.pdf これらの小さなデータセットの中央値が正規分布に収束するため、中央値のconf間隔を形成できるため、Ianのアプローチも気に入っています。
PeterR

10

ビニング手順のようなものはどうですか?(説明のために)値が100万から100万の間であることを知っていると仮定します。サイズSのN個のビンを設定します。したがって、S = 10000の場合、値[1:10000、10001:20000、...、990001:1000000]に対応する100個のビンがあります。

次に、値をステップ実行します。各値を保存する代わりに、適切なビンのカウンターをインクリメントするだけです。各ビンの中間点を推定値として使用して、中央値の合理的な近似値を作成できます。ビンのサイズを変更することで、必要に応じて解像度を微調整または粗調整できます。使用できるメモリの量によってのみ制限されます。

値がどれだけ大きくなるか分からないので、簡単なエンベロープ計算を使用して、メモリ不足になりそうにない十分な大きさのビンサイズを選択してください。また、値を含むビンのみを追加するように、ビンをまばらに保存することもできます。

編集:

ryfmが提供するリンクは、これを行う例を示しており、単に中間点を使用するのではなく、累積パーセンテージを使用して中央値ビン内の点をより正確に推定する追加のステップがあります。これは素晴らしい改善です。


ビニングアプローチの問題は、データの適切な上限がないため、最大ビンの中間点が巨大になる必要があることです。したがって、膨大な数のビン(そのための十分なメモリではない)が必要になるか、かなり広いビン(かなり不正確な答えになります)が必要になります。また、データはあまりまばらではありません。
PeterR

中央値のみに関心があるので、変数の値が大きいほどビンを広くできないのはなぜですか?
ラッセルピアス

drknexus-最大のビンがどうあるべきかわからないため。
PeterR

あなたは持っています任意の範囲がどうなるかに関して、直感を?回答の半分以上が数値Nを下回ることが確実な場合は、最後のビンを必要なだけ大きくすることができます。たぶんあなたの最後のビンはすべて1兆を超える数です-それは十分に高いでしょうか?最新のシステムのメモリ量により、大量のビンを保存し、かなり高い解像度を実現できます。データ構造に関しては、ここでは派手でメモリ集約型の話はしていません。
chrisamiller

直感はありますか?はい。そして、あなたのアプローチは一般的にうまくいくでしょう。ただし、この場合、多くのメモリ/計算を持つことはできません。これは、デバイスが毎秒数万のアイテムを見ることができ、この目的のために残っている処理が非常に少ないネットワーキングアプリケーションにあります。理想的/典型的なシナリオではない、私は知っているが、それはそれがそれを面白くするものです!
PeterR


8

リベスト- Tarjan-選択アルゴリズム(時々 、中央値の中央値-アルゴリズムと呼ばれる)を使用すると、任意の並べ替えなしに線形時間で中央値の要素を計算できるようになります。大規模なデータセットの場合、これは対数線形ソートよりもかなり高速です。ただし、メモリストレージの問題は解決しません。



2

私はこれをする必要がなかったので、これは単なる提案です。

2つの(他の)可能性があります。

ハーフデータ

  1. データの半分を読み込んで並べ替える
  2. 次に残りの値を読み取り、ソートされたリストと比較します。
    1. 新しい値が大きい場合は、破棄します。
    2. それ以外の場合は、ソートされたリストに値を配置し、そのリストから最大値を削除します。

標本分布

もう1つのオプションは、サンプリング分布を含む近似を使用することです。データが正常な場合、中程度のnの標準誤差は次のとおりです。

1.253 * sd / sqrt(n)

満足できるnのサイズを決定するために、Rで簡単なモンテカルロシミュレーションを実行しました。

n = 10000
outside.ci.uni = 0
outside.ci.nor = 0
N=1000
for(i in 1:N){
  #Theoretical median is 0
  uni = runif(n, -10, 10)
  nor  = rnorm(n, 0, 10)

  if(abs(median(uni)) > 1.96*1.253*sd(uni)/sqrt(n))
    outside.ci.uni = outside.ci.uni + 1

  if(abs(median(nor)) > 1.96*1.253*sd(nor)/sqrt(n))
    outside.ci.nor = outside.ci.nor + 1
}

outside.ci.uni/N
outside.ci.nor/N

n = 10000の場合、均一な中央値の推定値の15%がCIの外側にありました。


3
データセットは大きすぎて半分を読み取ることができない可能性があります...処理を行うデバイスが毎秒数万のアイテムを見ることができるネットワークコンテキストであり、おそらく数百だけを保存するのに十分なメモリがあります。また、データは間違いなくガウスではありません。実際、一般的なディストリビューションのいずれにもうまく適合しません。
PeterR


1

ここにstackoverflowで尋ねられた質問への答えがありますhttps : //stackoverflow.com/questions/1058813/on-line-iterator-algorithms-for-estimating-statistical-median-mode-skewness/2144754#2144754

反復更新の中央値+ = eta * sgn(sample-median)は、進むべき道のように思えます。


1
しかし、イータを選択する方法と、統計的にどういう意味ですか?すなわち、この結果から中央値の信頼区間を形成する方法は?
PeterR

@PeterR、ねえ、あなたが使用した最終的なソリューションは何ですか?
Aakash Goel

1

Remedianアルゴリズム(PDF)は、低いストレージ要件と明確に定義された精度で一通過メジアン推定を与えます。

基数bのレメディアンは、b個の観測値のグループの中央値を計算し、次にこれらの中央値の中央値を、単一の推定値のみが残るまで計算します。このメソッドは、サイズbのk個の配列(n = b ^ k)を必要とします...


1

場合の値を使用しているが、一定の範囲内にある、あなたが効率的に(BSDから撮影したこのコードは、EAのライセンスを取得した整数バケツと、値(たとえば、エントリ数兆)の非常に大きな数に中央値を計算することができ、100000に1を言います-utils / sam-stats.cpp)

class ibucket {
public:
    int tot;
    vector<int> dat;
    ibucket(int max) {dat.resize(max+1);tot=0;}
    int size() const {return tot;};

    int operator[] (int n) const {
        assert(n < size());
        int i;
        for (i=0;i<dat.size();++i) {
            if (n < dat[i]) {
                return i;
            }
            n-=dat[i];
        }
    }

    void push(int v) {
        assert(v<dat.size());
        ++dat[v];
        ++tot;
    }
};


template <class vtype>
double quantile(const vtype &vec, double p) {
        int l = vec.size();
        if (!l) return 0;
        double t = ((double)l-1)*p;
        int it = (int) t;
        int v=vec[it];
        if (t > (double)it) {
                return (v + (t-it) * (vec[it+1] - v));
        } else {
                return v;
        }
}

また、これはリアルタイムの中央値、などのためのビンの有限個使用して拡張することができます
エリックAronestyを
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.