最快的近似计数算法

时间:2012-11-26 07:16:45

标签: algorithm statistics machine-learning probability graph-algorithm

什么是获得输入文件或std out数据流的近似行数的最快方法。仅供参考,这是一个概率算法,我在网上找不到很多例子。

数据可能只是来自csv文件的awk脚本的一列或两列!让我们说我想在其中一个列上使用aprox groupby。我会使用数据库组,但行数超过6-7亿。我希望第一个近似结果在3到4秒内。然后在对先前做出决定之后运行贝叶斯或其他东西。关于一个非常粗略的初始组计数的任何想法?

如果你能在python或java中提供算法示例,那将非常有帮助。

2 个答案:

答案 0 :(得分:5)

如果你想计算总线数,@ Ben Allison的回答是一个好方法。既然你提到了贝叶斯和之前,我将在这个方向上添加一个答案来计算不同组的百分比。 (请参阅我对你的问题的评论。我想如果你对总数有所了解,如果你想做一个groupby,估计不同群体的百分比更有意义。)

递归贝叶斯更新:

我将首先假设您只有两个组(可以使用扩展程序使其适用于多个组,请参阅后面的解释。),group1group2

对于您处理的第一个m行(行)中的group1 n,我们将该事件表示为M(m,n)。显然,您会看到n-m group2,因为我们假设他们是唯一两个可能的群组。因此,您知道事件M(m,n)的条件概率给定group1s)的百分比,由具有n次试验的二项分布给出。我们正试图以贝叶斯方式估算s

二项式的共轭前缀是β分布。因此,为简单起见,我们选择Beta(1,1)作为先验(当然,您可以在alphabeta选择您自己的参数),这是(0,1)上的均匀分布。因此,对于此测试版分发,alpha=1beta=1

二项式+ beta先验的递归更新公式如下:

if group == 'group1':
    alpha = alpha + 1
else:
    beta = beta + 1

s的后验实际上也是一个beta分布:

                s^(m+alpha-1) (1-s)^(n-m+beta-1)
p(s| M(m,n)) = ----------------------------------- = Beta (m+alpha, n-m+beta)
                      B(m+alpha, n-m+beta)

其中Bbeta function。要报告估算结果,您可以依赖Beta distribution's均值和方差,其中:

mean = alpha/(alpha+beta)
var = alpha*beta/((alpha+beta)**2 * (alpha+beta+1))

python代码:groupby.py

stdin开始处理数据的几行python并估计group1的百分比如下所示:

import sys

alpha = 1.
beta = 1.

for line in sys.stdin:
    data = line.strip()
    if data == 'group1':
        alpha += 1.
    elif data == 'group2':
        beta += 1.
    else:
        continue

    mean = alpha/(alpha+beta)
    var = alpha*beta/((alpha+beta)**2 * (alpha+beta+1))
    print 'mean = %.3f, var = %.3f' % (mean, var)

样本数据

我向代码提供了几行数据:

group1
group1
group1
group1
group2
group2
group2
group1
group1
group1
group2
group1
group1
group1
group2  

近似估计结果

以下是我得到的结果:

mean = 0.667, var = 0.056
mean = 0.750, var = 0.037
mean = 0.800, var = 0.027
mean = 0.833, var = 0.020
mean = 0.714, var = 0.026
mean = 0.625, var = 0.026
mean = 0.556, var = 0.025
mean = 0.600, var = 0.022
mean = 0.636, var = 0.019
mean = 0.667, var = 0.017
mean = 0.615, var = 0.017
mean = 0.643, var = 0.015
mean = 0.667, var = 0.014
mean = 0.688, var = 0.013
mean = 0.647, var = 0.013

结果显示,在处理完第15行之前,group1估计有64.7%的百分比(基于之前的beta(1,1))。你可能会注意到方差不断缩小,因为我们有越来越多的观察点。

多个组

现在,如果您有两个以上的组,只需将下划线分布从二项式更改为多项式,然后相应的conjugate prior将是Dirichlet。其他一切你只是做出类似的改变。

进一步说明

你说你想在3-4秒内估计一下。在这种情况下,您只需对数据的一部分进行采样并将输出提供给上述脚本,例如

head -n100000 YOURDATA.txt | python groupby.py

就是这样。希望能帮助到你。

答案 1 :(得分:3)

如果假设数据是IID是合理的(因此没有偏差,例如在流的某些部分出现某些类型的记录),那么只需按照近似大小对子计数进行二次采样和放大。

说出前百万条记录(这应该可以在几秒钟内完成)。它的大小是 x 单位(MB,字符,无论你关心什么)。完整流的大小为 y ,其中 y >> X 。现在,从样本 x 中得出你关心的任何数量,并简单地用因子 y / * x *来计算它们的近似完全计数。例如:您想要在整个流中大致了解第1列的值为 v 的记录数。第一百万条记录的文件大小为100MB,而文件总大小为10GB。在第一百万条记录中,150,000条记录中第1列的值为 v 。因此,您假设在完整的10GB记录中,您将看到150,000 *(10,000,000,000 / 100,000,000)= 15,000,000值。您在样本上计算的任何统计数据都可以简单地按相同因子进行缩放,以产生估算值。

如果数据中存在偏差,使得某些记录或多或少可能位于文件的某些位置,那么您应该从总集中随机(或间隔均匀)选择样本记录。这将确保一个无偏见的,有代表性的样本,但可能会产生更大的I / O开销。

相关问题