动态监控分位数的算法


24

我想估计一些数据的分位数。数据是如此之大,以致无法容纳在内存中。而且数据不是静态的,新数据不断涌现。有人知道有什么算法可以用非常有限的内存和计算来监视到目前为止观察到的数据的分位数吗?我发现P2算法很有用,但是对于我的数据(尾部分布非常繁重)来说,效果并不理想。


有关一些想法(在估计中位数的背景下),请参见stats.stackexchange.com/q/346/919上的线程。
ub

3
这个问题交叉张贴在math.SE上。
主教

Answers:


16

P2算法是一个不错的发现。它通过对分位数进行几次估计,定期更新它们,以及使用二次(非线性,非三次)插值来估计分位数来工作。作者声称二次插值在尾部比线性插值效果更好,三次插值会变得过于繁琐和困难。

您没有确切说明这种方法对“重尾”数据如何失败,但是很容易猜测:在收集大量数据之前,对重尾分布的极端分位数的估计将是不稳定的。但是,即使您要存储所有数据,这也会(在较小程度上)成为一个问题,所以不要指望奇迹!

无论如何,为什么不设置辅助标记(我们将它们称为和,您可以肯定在其中确定分位数,并存储和之间的所有数据?当缓冲区填满时,您将必须更新这些标记,并始终保持。一个简单的算法可以通过组合(a)当前分位数的P2估计和(b)存储的小于的数据数量和大于的数据数量的。以这种方式,您可以像确定整个数据集始终可用一样,高确定性地估计分位数,但是您只需要一个相对较小的缓冲区即可。X 6 X 0 X 6 X 0X 6 X 0 X 6x0x6x0x6x0x6x0x6

具体来说,我提议一种数据结构来维护有关数据值的序列的部分信息。在这里,是一个链表n x 1x 2x n y(k,y,n)nx1,x2,,xny

y=(x[k+1](n)x[k+2](n)x[k+m](n)).

在这种表示法中,表示到目前为止读取的值中最小的。 是一个常数,是缓冲区的大小。 Ñ X ÿx[i](n)ithn xmy

该算法首先用遇到的前数据值填充并将它们按从小到大的排序顺序放置。令为要估计的分位数;例如, = 0.99。读取,可以执行以下三种操作: m q q x n + 1ymqqxn+1

  • 如果,则递增。 kxn+1<x[k+1](ñķ

  • 如果,则什么也不做。xn+1>x[k+m](n)

  • 否则, 插入。 ÿxn+1y

无论如何,将递增。ñ

所述插入件的过程放到以排序的顺序,然后消除在极端值中的一个: ÿ ÿXñ+1个ÿÿ

  • 如果,则从删除并增加;x n [ k + 1 ] y kķ+/2<ñqX[ķ+1个]ñÿķ

  • 否则,从删除。 yX[ķ+]ñÿ

如果足够大,则此过程将很有可能将分布的真实分位数括起来。在任何阶段都可以按照和 ,则可能位于。(我相信只需要像最大数据量()的平方根一样缩放,但是我没有进行严格的分析来证明这一点。)无论如何,该算法将检测它是否成功(通过比较和与)。Ñ X Ñ [ q Ñ] X Ñ [ q Ñ] ýñ ķ / Ñ ķ + / Ñ qñX[qñ]ñX[qñ]ñÿñķ/ñ(k+m)/nq

使用和(最困难的情况)对多达100,000个值进行测试,表明该算法在获得的正确值时成功率为99.5%。 。对于值的流,这将仅需要200万的缓冲区(但最好是3或400万)。在缓冲区中使用排序的双链表需要 =,同时标识和删除max(或min)是操作。相对昂贵的插入通常只需完成 q=0.5XÑ [ q Ñ] Ñ=10 12 Ö日志m=2Nq=.5x[qn](n)N=1012OlogNO1OO(log(N))O(log(N))O(1)ON+O(N)次。因此,该算法的计算成本为时间,存储时为。OO(N+Nlog(N))=O(N)O(N)


这是P2算法的扩展工作。[link] sim.sagepub.com/content/49/4/159.abstract。对于我的应用程序而言,存储空间仍然太大,该应用程序在具有总计10K RAM的小型传感器上运行。我最多只能消耗几百个字节用于分位数估计。
sinoTrinity 2011年

@whuber实际上,我实现了扩展的P2,并使用了来自各种分布(例如均匀分布和指数分布)的生成样本对其进行了测试,在这里效果很好。但是,当我将其应用于来自我的应用程序的数据(分布未知)时,有时它无法收敛并产生高达300%的相对误差(绝对(估计-实际)/实际)。
sinoTrinity 2011年

2
@sino 与使用所有数据相比,算法的质量不应该取决于尾巴的沉重程度。衡量误差的一种更公平的方法是:让为经验CDF。对于百分位数的估计,和什么区别?如果它是的数量级,那么您做得很好。换句话说,P2算法为您的数据返回多少百分比?q q ˚F q˚F q 1 / ÑFq^qF(q^)F(q)1/n
ub

你是对的。我刚刚测量了我提到的情况下的F(qˆ)和F(q),相对误差高达300%。对于0.7的q,qˆ几乎为0.7,误差可忽略不计。然而,对于0.9的q,qˆ似乎在0.95左右。我想这就是为什么我的错误高达300%。知道为什么它是0.95,而不是0.9吗?顺便说一句,我可以在此处发布图形吗?如何像您一样发布数学公式?
sinoTrinity

2
@whuber我非常有信心自己的实现符合扩展P2。当我同时估计0.8、0.85、0.9、0.95分位数时,0.9仍将达到0.95甚至更大。但是,如果同时跟踪0.8、0.85、0.9、0.95和1.0个分位数,则0.9非常接近0.9 。
sinoTrinity 2011年

5

我认为Whuber的建议很好,我会先尝试一下。但是,如果您发现您确实不能容纳存储或由于其他原因而无法解决问题,那么这里是对P2进行另一种概括的想法。它并不像胡佛所建议的那样详细-更像是研究思路,而不是解决方案。O(N)

就像原始P2算法建议的那样,您无需跟踪,,,和分位数,而只需跟踪更多的分位数(但仍为常数)即可。看起来该算法以一种非常直接的方式允许这样做;您需要做的就是为输入点计算正确的“存储桶”,以及更新分位数的正确方法(通常使用相邻数字)。p / 2 p 1 + p / 2 10p/2p(1+p)/21

假设您跟踪点。您可以尝试跟踪位于,,,,,,,的分位数,(等距地找出和之间以及和之间的点),甚至使用形式为和。如果0 p / 12 ... p 11 / 12 p p + 1 - p / 12 ... p + 11 1 - p / 12 1 0 p p 1个22 p / 2 1个+ COS 2 1 π250p/12p11/12pp+(1p)/12p+11(1p)/1210pp122 p/2(1+cos(2i1)π22)p+(1p)/2(1+cos(2i1)π22)p接近或,您可以尝试在质量概率较小的一侧放置较少的点,而在另一侧放置较多的点。01

如果您决定进行此操作,那么我(可能还有该网站上的其他人)将有兴趣知道它是否有效...


+1我认为,鉴于OP的限制,这是个好主意。一个人所希望的只是一个近似值,所以诀窍是选择那些很可能变窄并包含所需分位数的垃圾箱。
ub



2

我看一下分位数回归。您可以使用它来确定要查看的所有分位数的参数估计。它不对正态性做任何假设,因此可以很好地处理异方差性,并且可以滚动窗口使用。它基本上是L1-Norm的惩罚回归,因此它在数字上不太密集,并且有相当功能齐全的R,SAS和SPSS软件包以及一些matlab实现。这是主要R包Wiki的更多信息。

编辑:

查看数学堆栈交换交叉链接:有人找到了几篇论文,这些论文实质上提出了一个非常简单的想法,即只使用滚动顺序统计窗口来估计分位数。从字面上看,您要做的就是将值从最小到最大进行排序,选择所需的分位数,然后在该分位数内选择最高值。如果您认为最新的观察结果更能代表实际情况,则显然可以将其更多地考虑在内。这可能会给出粗略的估计,但是这样做相当简单,您不必进行定量繁重的工作。只是一个想法。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.