有估计位数,众数,偏度,和/或设定值的峰度的算法,但并不需要在内存中存储的所有值一次?
我想计算的基本统计:
- 意思是:算术平均
- 方差:平均偏差平方与平均值
- 标准偏差:方差的平方根
- 位数:值分隔较大数量的一半来自小一半
- 模式:在集中找到最频繁的价值
- 偏度:TL; 博士
- 峰度:TL; 博士
用于计算任何这些基本公式是等级学校的算法,我也认识他们。 有迹象表明,实施这些,还有许多统计库。
我的问题是在我处理组值的大量(10亿):在Python工作,我不能只让数十亿元素的列表或散列。 即使我写这在C,数十亿元素数组不是很实用。
该数据未排序。 它是随机产生的,在即时,其他进程。 每个集合的大小是高度可变的,并且尺寸不会提前知道。
我已经想通了如何处理的均值和方差非常好,通过以任意顺序设置的每个值迭代。 (实际上,在我的情况,我带他们在其中他们所产生的顺序。)下面是我使用的算法,礼貌http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm :
- 初始化三个变量:计数,总和,并sum_of_squares
- 对于每个值:
- 增计数。
- 添加到求和值。
- 添加值sum_of_squares的平方。
- 通过计分总和,存储作为变量均值。
- 通过计数除以sum_of_squares,存储作为变量mean_of_squares。
- 广场的意思是,存储为square_of_mean。
- 从mean_of_squares square_of_mean减去,存储为方差。
- 输出均值和方差。
这个“上线”算法有弱点(如精度问题sum_of_squares快速增长超过整数范围较大或浮动精度),但它基本上给我我需要什么,而不必存储在每一组的每一个值。
但我不知道估计附加统计(中位数,众,偏度,峰度)是否也存在类似的技术。 我可以与损害精度在一定程度上有偏估计器,或甚至一个方法住,只要处理的N个值所需要的内存比O(N)小得多。
指点我到现有的统计库将帮助也一样,如果库中有函数来计算这些行动“上线”的一个或多个。
Answer 1:
偏度和峰度
对于在线算法偏度和峰度(沿变化的线),看到在同一个wiki页面在这里对更高一刻统计的并行算法。
中位数
中位数是没有排序的数据强硬。 如果你知道,有多少数据点你,理论上你只需要部分地排序,例如,通过使用选择算法 。 然而,这并不能帮助太多数十亿值。 我会建议使用频率计数,请参阅下一节。
中位数,众同频数
如果是整数,我会算的频率 ,大概切断超过一定的价值,我相信它不再是相关的最高值和最低值。 对于花车(或太多的整数),我可能会创建桶/间隔,然后用同样的方法为整数。 (近似)模式和中值计算比变得容易,根据该频率表。
正态分布随机变量
如果是正态分布的,我会使用人群样本平均 , 方差 , 偏度和峰度作为最大似然估计的一小部分。 在(上线)算法,到现在已经计算出这些,你。 如读一对夫妇的十万或百万个数据点,直到你的估计误差变得足够小。 只要确保你从你的集合(例如,你不要采摘第一100'000值引入偏差)随机挑选。 相同的方法也可以用于估计模式和中位数为正常的情况下(对于样本均值是一个估计器)。
进一步的评论
所有的算法以上可以并行(包括许多分类和选择算法,例如快速排序和QuickSelect)运行,如果这有助于。
我一直认为(与正态分布的部分除外),我们谈论样本矩,中位数和模式,对于给定的一个已知分布理论的时刻没有估计。
通常,采样的数据(即,仅看一个子集)应该是相当成功的给定的数据量,只要所有的观察是相同的随机变量的实现方式(具有相同的分布)和时刻,模式和实际中位数存在此分布。 最后需要注意的是不是无害的。 例如,对于平均值(和所有高阶矩) 柯西分布是不存在的。 在这种情况下,“小”子集的样本均值可能从整个样本的样本均值是大规模关闭。
Answer 2:
我使用这些增量/递归平均数和中位数估计,这两者都使用常量存储:
mean += eta * (sample - mean)
median += eta * sgn(sample - median)
其中ETA是一个小的学习速率参数(例如0.001),SGN()是符号函数,其返回的一个{-1,0,1}。 如果数据是非平稳的(使用恒定的ETA和你想跟踪随时间的变化;否则,固定源,你可以使用像埃塔 = 1 / N的平均估计,其中n是看到了这么样的数量远......不幸的是,这似乎并没有为中位数估计工作。)
这种增量的平均估计的,似乎所有的地方,例如在无监督的神经网络学习规则被使用,但中位版本似乎不太常见,尽管它的好处(鲁棒性异常值)。 如此看来,中位数版本可以被用作许多应用中的平均估计的替代品。
我很想看到一个类似形式的增量模式估算...
UPDATE
我刚修改过的增量中位数估计估计任意位数。 在一般情况下,一个分位数函数( http://en.wikipedia.org/wiki/Quantile_function )告诉你将数据分成两个级分的值:p和1-P。 下面估计这个数值递增:
quantile += eta * (sgn(sample - quantile) + 2.0 * p - 1.0)
值p应为[0,1]之内。 这实质上将这个SGN()函数的对称输出{-1,0,1}对向一侧倾斜,所述数据样本划分成两个不相等尺寸的仓(馏分p和数据的1-p小于/大于分位数估计,分别地)。 请注意,对于p = 0.5,这减少至中值估计器。
Answer 3:
我实现了P-广场算法位数和直方图的动态计算,而不存储观察一个整洁的Python模块,我写叫LiveStats 。 它应该很有效地解决你的问题。 该库支持所有你提到除了模式统计。 我还没有发现模式估计一个满意的解决方案。
Answer 4:
瑞安,我怕你不这样做的均值和方差的权利......这想出了几个星期前在这里 。 而在线版(实际上由维尔福德的方法的名称去)的强项之一是事实,这是特别精确和稳定的,看到的讨论在这里 。 其中一个强项是,你并不需要保存平方的总额或总金额的事实...
我想不出任何上线的方法来模式和中位数,这似乎需要考虑一次全名单。 但它很可能是类似的做法不是一个方差和均值也将努力为偏度和峰度...
Answer 5:
维基百科的文章中引述的问题包含了calcualting上线偏度和峰度的公式。
对于模式 - 我相信 - 没有办法这样做就行。 为什么? 假设你输入的所有值,除了最后一个复制前一个不同。 在这种情况下,你要记住,媒体链接出现在输入所有值检测,最后的值复制看到befor值,并使它成为最频繁的一个。
对于中位数几乎是一样的 - 给你不知道什么值将成为位数,如果所有输入值是不同的,因为它可能是之前或当前正中后,最后输入。 如果您知道输入的长度,你可以找到位数不存储在内存中的所有值,但是你仍然必须存储很多(我猜周围的一半),因为一个坏的输入序列可能在很大程度上转移位数第二半可能使从第一半中值的任何值。
(请注意,我指的只是精确的计算。)
Answer 6:
如果你有几十亿个数据点,那么它不太可能,你需要确切的答案,而不是封闭的答案。 一般来说,如果你有几十亿个数据点基本过程产生他们很可能会遵循某种统计平稳/遍历/混合性的。 此外,它可不管你是否希望分布是合理的连续或不连续。
在这种情况下,存在对上线,低内存,分位数的估计 (中位数为0.5分位数的特殊情况)的算法,以及模式,如果你并不需要确切的答案。 这是统计的活跃领域。
位数估计例如: http://www.computer.org/portal/web/csdl/doi/10.1109/WSC.2006.323014
模式估计例如:比克尔DR。 连续数据的模式和偏度的鲁棒估计。 计算统计和数据分析。 2002; 39:153-163。 DOI:10.1016 / S0167-9473(01)00057-3。
这些都是计算的统计活跃的领域。 您正在进入的领域,其中没有任何一个最好的精确算法,但它们的多样性(统计估计,在真理),它有不同的属性,假设和性能。 这是实验数学。 可能有成百上千的关于这个问题的论文。
最后一个问题是你是否真的需要偏度和峰度自己,或者更可能这可能是在表征概率分布更可靠一些其他参数(假设你有一个概率分布!)。 你是否期待一个高斯?
你有/清洁的方式预处理的数据,更主要是Gaussianish? (例如,金融交易金额往往采取对数后有所高斯)。 你期望有限的标准偏差? 你期望肥尾? 你是在尾部或散装关心的数量吗?
Answer 7:
每个人都在说,你不能做的模式在网上的方式,但是这是不正确的。 下面是一个文章描述了一个算法来做到这本由迈克尔·菲舍尔和耶鲁大学的史蒂芬L. Salzberg于1982年发明了很的问题。 从文章:
大多数调查算法使用其寄存器用于从所述流中的单个项目的临时存储中的一个; 这个项目是大多数元件的电流候选人。 所述第二寄存器被初始化为0。对于流中的每个元素的计数器,我们要求该算法执行以下例程。 如果计数器读数为0,安装当前流元素作为新的多数候选人(移动,可能已经在寄存器中的任何其他元素)。 然后,如果当前元素多数候选人匹配,增加计数器; 否则,递减计数器。 在周期的这个阶段,如果迄今为止看到的数据流的部分有大部分元素,该元素是在候选人登记,并反向握持大于0,如果什么也没有大多数元素更高的价值? 不通过数据,这是不可能在一个流进行第二遍环境的算法不能总是给在这种情况下一个明确的答案。 它只是承诺正确识别大部分元素(如果有)。
它也可以扩展到找到更多的内存的前N但这应该解决这个问题的方式。
Answer 8:
最后,如果你有分布,我认为你必须存储所有的值没有先验知识的参数。
也就是说,除非你正在处理某种病理情况,remedian(Rousseuw和巴塞特1990年)可能是不够好你的目的。
很简单它涉及到计算中位数批次的中位数。
Answer 9:
中位数和众不能使用仅提供恒定的空间在线计算。 但是,由于中位数和众反正是比“量”更“描述性”,可以通过采样数据集估计它们如。
如果数据是正态分布的,从长远来看,那么你可以只用你的平均估计值。
您也可以估算平均使用以下方法:建立一个中位数估计M [I]每一个,比方说,在数据流中1,000,000条记录,使M [0]是第一个万个条目的中位数,M [1]第二百万条目等中值,然后使用M [0],...,M [K]的值作为中值估计器。 当然,这节省了空间,还可以控制你多么希望通过“微调”参数1,000,000利用空间。 这可以递归也一概而论。
Answer 10:
OK花花公子尝试这些:
对于C ++:
double skew(double* v, unsigned long n){
double sigma = pow(svar(v, n), 0.5);
double mu = avg(v, n);
double* t;
t = new double[n];
for(unsigned long i = 0; i < n; ++i){
t[i] = pow((v[i] - mu)/sigma, 3);
}
double ret = avg(t, n);
delete [] t;
return ret;
}
double kurt(double* v, double n){
double sigma = pow(svar(v, n), 0.5);
double mu = avg(v, n);
double* t;
t = new double[n];
for(unsigned long i = 0; i < n; ++i){
t[i] = pow( ((v[i] - mu[i]) / sigma) , 4) - 3;
}
double ret = avg(t, n);
delete [] t;
return ret;
}
在那里你说你已经可以计算样本方差(SVAR)和平均值(AVG),你点那些你的功能上来一点。
另外,看看皮尔森近似的事情。 在这样一个大的数据集这将是非常相似的。 3(平均值 - 中位数)/标准偏差必须位数作为最大 - 最小/ 2
对于花车模式已经没有任何意义。 人们通常会坚持他们的sginificant大小的垃圾箱(如1/100 *(最大值 - 最小值))。
Answer 11:
这个问题已经解决由Pebay等:
https://prod-ng.sandia.gov/techlib-noauth/access-control.cgi/2008/086212.pdf
Answer 12:
我会倾向于使用水桶,这可能是适应性的。 桶的大小应该是你所需要的精度。 然后,每个数据点进来你添加一个到相关的桶的数量。 这应该给你简单的近似中值和峰度,通过计算每个桶作为其计加权值。
有一个问题可能是分辨率的损失在浮点后达数十亿,即增加一个不改变价值的多! 为了避开这个问题,如果最大桶大小超过一定限度,你可能需要大量关闭所有的罪名。
Answer 13:
for j in range (1,M):
y=np.zeros(M) # build the vector y
y[0]=y0
#generate the white noise
eps=npr.randn(M-1)*np.sqrt(var)
#increment the y vector
for k in range(1,T):
y[k]=corr*y[k-1]+eps[k-1]
yy[j]=y
list.append(y)
文章来源: “On-line” (iterator) algorithms for estimating statistical median, mode, skewness, kurtosis?