Statistics 大字节数组的精确运行统计平均值

Statistics 大字节数组的精确运行统计平均值,statistics,bytearray,overflow,mean,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); for(int i = 0; i < samples.length; i++){ byte diff = sam

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

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);
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) )))
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
My findMean函数继续填充以下内容:

mean[k] = mean(samples[:][k])
到目前为止还很简单。问题是,由于溢出问题,这个均值函数不能简单地进行求和和和除法。因此,我目前的尝试是计算一个运行平均值,其主要内容如下:

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);
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) )))
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
for(int i=0;i
现在这根本不起作用,每一轮的精度损失都会导致平均值与正确值相差很远,我已经在1000个随机样本的小集合(因此可计算)上验证了这一点

此外,由于内存问题,我正试图通过首先使用字节数组来避免这些问题,因此不可能分配一个大的代理浮点数组来计算真正的平均值,然后再转换为一个字节

将这些数据分块加载是……嗯,这是可能的,但我正在考虑我的最后一个选择,不管怎样,这只会将问题转移到块大小上

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


Cheers

您可以使用更大的整数类型(long/bigInt),甚至可以使用它来计算总和。在这种情况下,您实际上不需要在线算法,尽管保留它除了降低计算速度之外不会产生任何影响


当你用总和除以计数来计算平均数时,你当然会受到你所使用的浮点类型精度的限制,所以要记住这一点。如果你采用APA方法,这将不会是一个问题。

如果你计算128个平均数,你就不能分配128个双精度(dmean[]say)要抓住它们,请使用

双差=样本[i][k]-dmean[k]

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


要更新平均值?

对。所以我决定至少要保留一个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[][]来保存当前的运行平均值。因此,我现在重新安排了我的循环,使其看起来更像这样:

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);
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) )))
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
这种方法需要一些预处理,我需要循环所有样本,以找到哪些样本将更新哪些数组(单个索引数组),但我的总体节省是,我现在可以为每个样本保存一个更新的双精度数组,该双精度数组将为该样本的给定维度更新给定数组

然后可以将这个double转换为适当的低精度类型,在我的例子中是一个字节

就存储空间而言,我最初希望的总体节约是:

将整数(成本为4*128*numberOfSamples)替换为字节(成本为1*128*numberOfSamples)

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

是的,我们开始了,晚上睡觉,我回答了我自己的问题


谢谢大家的帮助!

不,不幸的是,对于整个样本集,这将很快变得相当昂贵。我通过重新排列用于计算平均值的循环修复了这个问题,我在上面已经解释过,使用较大的整数类型将占用更多内存,即使只保留在平均值为b的期间经过计算,将导致超出合理的开销。最后,我通过重新安排用于计算平均值的循环来解决此问题,无论如何,谢谢!:-)一个长循环将再花费四个字节,并且不太可能溢出。这将是一个非常实用的方法。