基数统计:从Linear Counting到Hyper LogLog

欢迎来我的小站转转~~

应用场景

基数统计(Cardinality Counting)指计算一个数据集中不同元素的数量,在很多场景都需要这样的功能:电商场景中的独立用户(UV)数量统计、数据库中快速计算字段取值数量以优化query、计算与某个站点相关的不同链接数量等。

为实现这样的功能,最直观的方法就是使用 Set 记录每一个元素,在数量巨大的情况下,会造成大量的内存占用。以存储 2 30 2^{30} 230 (约10亿)个长度为64bit的url为例,需要占用 64 ∗ 2 30 = 64 G B 64*2^{30} = 64GB 64230=64GB 的空间。Set方案的空间占用与元素的数量成正比,空间复杂度为 O ( N ) O(N) O(N)

如果使用bitmap来存储,则需要将不同的url映射到不同的数字。即使最理想的情况下,url之间没有冲突,且从1到 2 30 2^{30} 230 都没有空闲,bitmap也需要占用 2 30 ÷ 8 = 2 27 = 128 M B 2^{30}\div 8 = 2^{27} = 128MB 230÷8=227=128MB 的空间。bitmap方案占用空间只与最大取值有关系,与元素数量无关。极端情况下,即使只有一个url,在这个例子中也需要占用128MB的空间,空间复杂度为 O ( N m a x ) O(N_{max}) O(Nmax)

以上两种方式都对基数进行精确统计,但是很多时候只需要一个大概的数量,只要误差在一定范围内即可。接下来要讨论的几种算法可以在牺牲一定精确性的情况下,大幅度降低空间占用。

Linear Counting

诞生于1990年的论文“A linear-time probabilistic counting algorithm for database applications“,相比bitmap有常数项的空间复杂度优化,但整体还是 O ( N m a x ) O(N_{max}) O(Nmax)

在这里插入图片描述

主要步骤

  1. 数据哈希:假设原始数据的基数为n,使用一组哈希空间为m的哈希函数H,将原始数据均匀分组。
  2. 分桶数据统计:构建一个长度为m的bitmap,其中每一个bit对应哈希空间的一个值。生成哈希数组的值如果存在,则把相应的bit设置为1。
  3. 数量估计:当所有值设置完成后,统计bitmap中为0的bit数为u。则估计的基数为 n ^ = − m log ⁡ u m \hat{n} = -m \log {\frac{u}{m}} n^=mlogmu

基数公式推导

记事件 A j A_j Aj 为“经过n个数字哈希之后,桶j仍然为空”,则 P ( A j ) = ( 1 − 1 m ) n P(A_j) = (1-\frac{1}{m})^n P(Aj)=(1m1)n

U n U_n Un 为经过n个数字哈希之后,仍然为空的桶数量。因为各个桶之间互相独立,所以 E ( U n ) = m ( 1 − 1 m ) n = m [ ( 1 + 1 − m ) − m ] − n m E(U_n) = m(1-\frac{1}{m})^n = m[(1+\frac{1}{-m})^{-m}]^{-\frac{n}{m}} E(Un)=m(1m1)n=m[(1+m1)m]mn

当m趋向于无穷大时, lim ⁡ m → ∞ E ( U n ) = lim ⁡ m → ∞ m [ ( 1 + 1 − m ) − m ] − n m = m e − n m \lim_{m \to \infty} E(U_n) = \lim_{m \to \infty } m[(1+\frac{1}{-m})^{-m}]^{-\frac{n}{m}} = me^{-\frac{n}{m}} limmE(Un)=limmm[(1+m1)m]mn=memn

得到 n = − m log ⁡ E ( U n ) m n = -m \log{\frac{E(U_n)}{m}} n=mlogmE(Un)

由于每个桶的取值都服从参数相同的0-1分布,所以 U n U_n Un符合二项分布。当n很大的时候,可以用正态分布逼近二项分布, U n U_n Un 的概率密度函数为:

f ( x ) = 1 σ 2 π e − ( x − μ ) 2 2 σ 2 f(x) = \frac{1}{\sigma \sqrt{2\pi}} e^{-\frac{(x-\mu)^2}{2{\sigma}^2}} f(x)=σ2π 1e2σ2(xμ)2

因此我们实际观察到的空桶数量 u u u 可以作为 E ( U n ) E(U_n) E(Un) 的无偏估计,由于 = − m log ⁡ x m = -m \log{\frac{x}{m}} =mlogmx 是可逆函数,可以把 n ^ \hat{n} n^ 作为理论 n n n 的无偏估计。

误差估计

偏差

记装载因子 t = n m t=\frac{n}{m} t=mn , 空桶比例 V n = U n m V_n = \frac{U_n}{m} Vn=mUn , 空桶数量期望 p = E ( V n ) = E ( U n ) m = e − n m = e − t p = E(V_n)=\frac{E(U_n)}{m} = e^{-\frac{n}{m}} = e^{-t} p=E(Vn)=mE(Un)=emn=et

− ln ⁡ ( V n ) = f ( V n ) -\ln(V_n) = f(V_n) ln(Vn)=f(Vn),则 n ^ = m ∗ ( − ln ⁡ u m ) = m f ( V n ) \hat{n} = m*(-\ln{\frac{u}{m}})=mf(V_n) n^=m(lnmu)=mf(Vn)

V n V_n Vn 处进行泰勒展式:

n ^ = m f ( V n ) = m ( f ( p ) + ( V n − p ) f ′ ( p ) + 1 2 ( V n − p ) 2 f ′ ′ ( p ) + 1 6 ( V n − p ) 3 f ′ ′ ′ ( p ) . . . . ) \hat{n} = mf(V_n) = m(f(p)+(V_n-p)f'(p)+\frac{1}{2}(V_n-p)^2f''(p)+\frac{1}{6}(V_n-p)^3f'''(p)....) n^=mf(Vn)=m(f(p)+(Vnp)f(p)+21(Vnp)2f(p)+61(Vnp)3f

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值