准确运行大量字节的统计平均值

时间:2010-09-02 17:09:55

标签: statistics bytearray overflow mean

我有一个二维字节数组,如下所示:

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个随机样本集上进行了验证。

另外,由于我首先尝试通过使用字节数组来避免内存问题,因此很难分配一个大的代理浮点数来计算真实均值,然后转换为一个字节。

以块的形式加载这些数据是......好吧,但是我正在考虑我的最终替代方案,无论如何,这只是将问题转移到块大小?

无论如何,使用运行算法准确计算字节数组的均值,以避免溢出问题。这里有一个很好的解决方案吗?

干杯

3 个答案:

答案 0 :(得分:2)

您可以使用更大尺寸的整数类型(long / bigInt),甚至arbitrary precision arithmetic来计算总和。在这种情况下,您并不真正需要在线算法,尽管保持它不会产生任何影响,除了使计算更慢。

当您将总和除以计算平均值时,您当然会受到您使用的浮点类型的精度限制,因此请记住这一点。如果你走下APA路线,这将不是问题。

答案 1 :(得分:0)

如果您正在计算128种手段,您可以负担得起128个双打(dmean []说)来保留它们,请使用

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

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

更新平均值?

答案 2 :(得分:0)

右。所以我决定至少要拿双倍来计算任何给定维度的均值。

问题是我正在通过以下方式解决这个问题:

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

这种方式需要一些预处理,我需要循环遍历所有样本以找到哪些样本将更新哪些数组(单个indecies数组)但我的整体保存是我现在可以保存一个更新的SINGLE对于每个样本,更新该样本的给定维度的给定数组。

然后可以将此double转换为适当的低精度类型,在我的情况下,为一个字节。

我最初的存储空间总体节省是:

用字节替换整数(花费4 * 128 * numberOfSamples)(花费1 * 128 * numberOfSamples)

这不起作用,但我现在已经制定了一个解决方案,其成本如下:(128 * numberOfSamples + numberOfSamples)。节省了127 * numberOfSamples。在我最糟糕的情况下,接近15Gb RAM: - )

所以是的,我们去,睡了一夜,我回答了自己的问题。

感谢帮助伙伴们!