当前位置:  开发笔记 > 编程语言 > 正文

用于估计统计中位数,模式,偏度,峰度的"在线"(迭代器)算法?

如何解决《用于估计统计中位数,模式,偏度,峰度的"在线"(迭代器)算法?》经验,为你挑选了4个好方法。

是否有算法来估计值集的中值,模式,偏度和/或峰度,但这不需要一次将所有值存储在内存中?

我想计算基本的统计数据:

平均值:算术平均值

方差:平均偏差的平均值

标准差:方差的平方根

中位数:将较大一半的数字与较小的一半分开的值

mode:在集合中找到最频繁的值

偏斜:tl; 博士

峰度:tl; 博士

计算任何这些的基本公式是小学算术,我知道它们.还有许多统计库可以实现它们.

我的问题是我正在处理的集合中的大量(数十亿)值:在Python中工作,我不能只使用数十亿个元素创建列表或哈希.即使我用C语言编写,十亿元素数组也不太实用.

数据未排序.它是由其他过程随机,即时生成的.每组的大小变化很大,并且不会提前知道大小.

我已经弄清楚如何很好地处理均值和方差,以任何顺序迭代集合中的每个值.(实际上,在我的情况下,我按照它们生成的顺序来看它们.)这是我正在使用的算法,礼貌http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm:

初始化三个变量:count,sum和sum_of_squares

对于每个值:

增量计数.

将值添加到sum.

将值的平方添加到sum_of_squares.

按计数除以总和,作为变量均值存储.

将sum_of_squares除以count,存储为变量mean_of_squares.

平方均值,存储为square_of_mean.

从mean_of_squares中减去square_of_mean,存储为方差.

输出均值和方差.

这种"在线"算法存在缺陷(例如,精度问题,因为sum_of_squares快速增长大于整数范围或浮点精度),但它基本上给了我所需要的,而不必存储每个集合中的每个值.

但我不知道是否存在类似的技术来估计额外的统计数据(中位数,模式,偏度,峰度).只要处理N值所需的内存远小于O(N),我就可以使用有偏差的估计器,或者甚至是在一定程度上损害精度的方法.

如果库具有"在线"计算这些操作中的一个或多个的功能,那么将我指向现有的统计库也会有所帮助.



1> Tyler Street..:

我使用这些增量/递归均值和中值估计值,它们都使用常量存储:

mean += eta * (sample - mean)
median += eta * sgn(sample - median)

其中eta是一个小的学习速率参数(例如0.001),而sgn()是signum函数,它返回{-1,0,1}中的一个.(如果数据是非平稳的并且您想跟踪随时间的变化,则使用常数eta ;否则,对于静止源,您可以使用类似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,这会降低到中值估计量.


这对于平均而言非常有用,但是我没有看到它如何产生远离中位数的任何东西.取一系列millisec时间戳,例如:`[1328083200000,981014400000,-628444800000,318240000000,949392000000]`,其中位数为"318240000000".该等式将先前的中位数移动+/-`eta`,其推荐值为0.001.对于像这样的大数字,这不会做任何事情,对于真正的小数字来说,这可能太大了.如果不事先知道答案,你会如何选择一个真正给你正确答案的`eta`?
想象一下,数字有单位,例如毫米.然后很明显eta(对于中位数的估计)必须具有与测量相同的单位,因此像0.001这样的通用值根本没有任何意义.一个看似更好的方法是从绝对偏差的运行估计中设置eta:对于每个新值`sample`,更新`cumadev + = abs(sample-median)`.然后设置`eta = 1.5*cumadev /(k*k)`,其中`k`是到目前为止看到的样本数.
这个中位数估算器很棒.你知道0.25/0.75分位数是否有相似的估算器?
@Gacek:我刚用增量方法更新了我的答案来估算任何分位数,你可以在[0,1]内将p设置为0.25,0.75或*任意*值.

2> stephan..:

偏斜和Kurtosis

对于Skewness和Kurtosis的在线算法(沿着方差线),请在同一个wiki页面中查看更高时刻统计的并行算法.

中位数

没有分类数据,中位数很难.如果你知道,你有多少数据点,理论上你只需要部分排序,例如使用选择算法.然而,这对数十亿的价值观没有多大帮助.我建议使用频率计数,请参阅下一节.

具有频率计数的中位数和模式

如果它是整数,我会计算 频率,可能会切断超出某个值的最高值和最低值,我确信它不再相关.对于浮点数(或者整数太多),我可能会创建存储桶/间隔,然后使用与整数相同的方法.(近似)模式和中值计算比根据频率表变得容易.

常规分布随机变量

如果它是正态分布的,我会使用总体样本均值,方差,偏度和峰度作为小子集的最大似然估计.用于计算这些的(在线)算法,你现在已经.例如,读取数十万或数百万个数据点,直到您的估计误差变得足够小.只需确保从您的集合中随机选择(例如,您不会通过选择前100'000值来引入偏差).相同的方法也可以用于估计正常情况的模式和中值(对于样本均值是估计量).

进一步评论

上述所有算法都可以并行运行(包括许多排序和选择算法,例如QuickSort和QuickSelect),如果这有帮助的话.

我一直假设(除了关于正态分布的部分)我们讨论样本矩,中位数和模式,而不是给定已知分布的理论矩的估计.

一般来说,对数据进行采样(即仅查看子集)应该非常成功,只要所有观察都是相同随机变量(具有相同的分布)以及时刻,模式和这个分布实际存在中位数.最后一个警告并非无害.例如,不存在Cauchy分布的均值(和所有更高的矩).在这种情况下,"小"子集的样本平均值可能与整个样本的样本平均值大量偏离.



3> 小智..:

我在一个名为LiveStats的简洁Python模块中实现了P-Square算法,用于动态计算分位数和直方图而无需存储观察.它应该非常有效地解决你的问题.除了模式之外,该库支持您提到的每个统计信息.我还没有找到一个令人满意的模式估计解决方案.



4> Jaime..:

瑞恩,我担心你没有做出正确和差异的权利......这几周前就出现了.而在线版本的一个优点(实际上是韦尔福德方法的名称)是它特别准确和稳定的事实,请参阅此处的讨论.其中一个优点是你不需要存储总和或总和的总和......

我想不出任何模式和中位数的在线方法,这似乎需要立即考虑整个列表.但是,与方差和均值相似的方法很可能也适用于偏度和峰度......

推荐阅读
TXCWB_523
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有