web-dev-qa-db-ja.com

高速/効率的なヒストグラムアルゴリズムの検索(事前に指定されたビンを使用)

Matlabの外では多くのコーディングを行いませんが、Matlabコードを別の言語(おそらくC)にエクスポートする必要があります。Matlabコードには、入力データを配置するヒストグラム関数histc()が含まれています(これはdoubleです) -精度ではなく整数)を指定されたビンの配列に入れて、ヒストグラムを形成します。

ヒストグラム関数を生成するためにいくつかのネストされたループをつなぎ合わせることができると確信していますが、この関数は繰り返しアクセスされ、頻繁にアクセスされるため、高速でメモリ使用量が少ないことが必要です。

ホイールの再発明を回避するために、C言語で使用できる既存のヒストグラム関数があるかどうか、または一般にそのようなものが必要な人がそれを自分で作成するかどうかを誰もが知っていますか?

誰かがヒストグラムを作成するための効率的なアルゴリズムを知っていますか?疑似コードで結構です。

前もって感謝します。

24
ggkmath

GSL(GNU Scientific Library)には、ヒストグラムの実装が含まれています。

ここにドキュメントがあります: http://www.gnu.org/software/gsl/manual/html_node/Histograms.html

そして、これが使用例です http://www.gnu.org/software/gsl/manual/html_node/Example-programs-for-histograms.html

15
Kyle Lutz

「理想的な」ヒストグラムアルゴリズムは、キャプチャする予定の範囲によって異なります。一般に、ヒストグラムアルゴリズムは次のようになります。

_const int NSAMPLES = whatever;
double samples[NSAMPLES] = { 1.0, 3.93, 1e30, ... }; // your data set
const int NBUCKETS = 10; // or whatever
int counts[NBUCKETS] = { 0 };
for (int i = 0; i != NSAMPLES; ++i) {
    counts[TRANSFER(samples[i])]++;
}
_

ここで、TRANSFER()は、入力をビンにマップする関数です(0番目またはN番目のビンは、該当する「範囲外」にマップされます)。

TRANSFER()の正確な実装は、サンプルの予想される分布と詳細に関心がある場所に大きく依存します。私が見たいくつかの一般的なアプローチ:

  • 範囲[a、b]の均一分布(線形変換が必要)
  • 符号なし整数値の対数分布(いくつかの bit twiddling hacks と組み合わせると、最も近い2のべき乗などをすばやく決定するのに最適です)。

事前に分布がわからない場合、効果的にそれらを効果的に分類するための効率的なメカニズムを実際に持つことはできません。推測(バイアスされた結果または有益でない結果)を推測するか、すべてを保存して最後に並べ替える必要があります。同じサイズのバケットへのビニング(パフォーマンスの低下)。

20
Tom

私は自分のヒストグラムコードをCで記述しました。ライブラリを探すつもりもなかったほど簡単なためです。通常、必要なビンの数を含む配列を作成する必要があります[num_bins = (int)(val_max - val_min + 1);]。各サンプルに遭遇したら、ビンの数で除算できます[bin_idx = (int)((value - val_min) / bin_width);] (where bin_width = (max-min)/num_bins)が属している場所を見つけ、ビンカウンターをインクリメントします。これは、データを簡単、高速、シングルパスで処理します。上記の私の計算でEdgeケースを確認してください。

発生する可能性がある問題は、入力のドメインが不明である可能性があることです。 doubleの範囲全体に100個のビンを配置しても、すべてのデータがそのごく一部に含まれている場合は、あまり効果がありません。解決策は、データの最初のパスを作成して、範囲の最小/最大を見つけることです。これに対する迅速な修正は実際にはなく、ほとんどのライブラリは事前に最小/最大を要求します。

12
dwc