0

次のようなバイトの2次元配列があります。

int n = 100000;
int d = 128;
byte[][] samples = new byte[n][d]
/* proceed to fill samples with some delicious data */
byte[] mean = new byte[d];
findMean(mean,samples);

私の findMean 関数は、次のような平均を埋めます。

mean[k] = mean(samples[:][k])

これまでのところ十分に単純です。問題は、オーバーフローの問題により、この平均関数は単純に合計と除算を行うことができないことです。したがって、私の現在の試みは、移動平均を計算することです。その主力は次のようになります。

for(int i = 0; i < samples.length; i++){
    byte diff = samples[i][k] - mean[k]
    mean[k] = (byte)((double)mean[k] + (Math.round( (double) ( diff ) / (double) (i + 1) )))

これはまったく機能しません。ラウンドごとに精度が低下するため、平均値が正しい値からかなり離れています。これは、1000個のランダムサンプルの小さな(したがって計算可能な)セットで検証しました。

また、最初にバイト配列を使用して回避しようとしているメモリの問題が原因で、大きなプロキシ float 配列を割り当てて真の平均を計算し、後でバイトにキャストすることはまったく不可能です。

このデータをチャンクでロードすることは...可能ですが、最終的な代替手段を考えていますが、とにかく、それは問題をチャンクサイズに置き換えるだけですか?

とにかく、実行中のアルゴリズムを使用してバイト配列の平均を正確に計算し、オーバーフローの問題を回避します。ここに良い解決策はありますか?

乾杯

4

3 に答える 3

2

合計を計算するには、より大きなサイズの整数型 (long / bigInt)、または任意精度の算術演算を使用できます。この場合、オンライン アルゴリズムは実際には必要ありませんが、オンライン アルゴリズムを保持しても計算が遅くなる以外に影響はありません。

合計をカウントで割って平均を計算する場合は、もちろん、使用している浮動小数点型の精度によって制限されるため、その点に注意してください。APA ルートを下る場合、これは問題になりません。

于 2010-09-02T17:14:22.377 に答える
0

128 の手段を計算している場合、それらを保持するために 128 の double (dmean[] など) を割り当てる余裕がない場合は、次を使用します。

double diff = samples[i][k] - dmean[k];

dmean[k] = dmean[k] + diff/(i+1) ;

平均を更新するには?

于 2010-09-02T17:23:07.347 に答える
0

右。したがって、特定の次元の平均を計算するには、少なくとも double を保持する必要があると判断しました。

問題は、次のようにしてこの問題に近づいていたことです。

for each sample, get the array it is to update
    for each dimension in that array, calculate it's running mean given the new sample

その問題は、更新する各要素の各次元の現在の移動平均を保持する double[][] を保持する必要があることです。したがって、ループを次のように再配置しました。

for each array to be updated
    for each sample that will update this array
        for each dimension in the array to be updated calculate the running mean

この方法では、前処理が必要です。すべてのサンプルをループして、どのサンプルがどの配列 (単一のインデックス配列) を更新するかを見つける必要がありますが、全体的な節約は、サンプルごとに更新される SINGLE double を保持できることです。そのサンプルの特定の次元の特定の配列を更新します。

この double は、適切な低精度型 (私の場合はバイト) にキャストできます。

私が最初に目指していたストレージスペースの全体的な節約は次のとおりです。

Integers (コスト 4*128*numberOfSamples) を Bytes (コスト 1*128*numberOfSamples) に置き換えます。

それはうまくいきませんでしたが、私は今、(128*numberOfSamples + numberOfSamples) のようなコストのソリューションを作成しました。127*numberOfSamples の節約。私の最悪のケースでは、15GbのRAMに近づいています:-)

ええ、それでは、一晩寝て、私は自分の質問に答えました。

助けてくれてありがとう!

于 2010-09-03T12:52:58.957 に答える