HyperLogLog 算法纪要

最近在OLAP中使用到HyperLogLog算法,所以做过简单的学习笔记。主要翻译自维基百科。

简介:

HyperLogLog算法的基础是观察到这样的现象:包含正态分布随机数的多集的基数可以通过计算集合中每个数的二进制表示中前缀零的数量来估算。如果前缀零的最大数量是n,那么集合中独立元素的数量的估计值约为2n

在HyperLogLog算法中,对原始多集的每一个元素进行hash映射,已得到一个具有和原始多集相同基数正态分布随机数的多集。新的随机正态集合的基数可以使用上面提到的算法估算。

使用上述算法进行简单的估算具有方差大的缺点。在HyperLogLog算法中,方差通过将多集分解为很多子集来最小化,在每个子集中计算前缀零数量的最大值,并使用调和平均数来结合自己的估计值结果从而得到整体的估计值。

 

算法的实现分为三个主要步骤:Add、Count和Merge。

Add:将一个新的元素加入集合

Count:计算集合的基数

Merge:计算两个集合的并集

结合merge和count操作还可以通过容斥原理实现一些派生操作,比如:交集的基数、差集的基数。

HyperLogLog的数据存储在大小为m的计数器(称为register「条目」)数组M里,其初始值为0

Add:

Add操作如下:

使用函数h计算输入数据v的hash,取前b位(其中b是log2(m)),然后加1后得到需要修改的条目的地址。对其余的位计算,即最左侧的1。将条目的值更新为其原始值和中的较大者。

 

Count:

Count算法如下:

计算m个条目的调和平均数,并使用一个常数来推算估计值E:

 

 

直观的,n是M的未知基数,每个子集Mj大约有n/m个元素。那么应当接近(译者注:我们先记为X吧)。2的这么X次方的调和平均数为mZ,其值应当接近n/m。所以m2Z应该近似于n。

最后,常量的引入是为了修正哈希碰撞导致m2Z所具有的系统乘性偏差(systematic multiplicative bias)

 

 

 

实现上的考虑:

常量并不容易计算,但是可以使用下面的共识近似:

HyperLogLog技术在小于阈值的基数上仍然有明显的偏移。原论文提出对于小基数使用称为线性计数的不同算法。在上述方法给出的估计值低于阈值时,可以使用该替代计算:

  1. 令 V 是值为0的条目数量。
  2. 如果V=0,使用上面标准的HyperLogLog估算E。
  3. 否则,使用线性计数:

另外,对每个计数过大接近条目极限的情况(比如,对于一个32位的条目,)基数的估算方式可以使用下式:

通过上述对下限和上限情形的修正,误差可以估计为:

Merge:

两个HLL (hll1,hll2) 的merge操作通过取每一项条目的最大值来进行:j:1..m

 

变种:维基百科提到了两个变种(HyperLogLog++、Streaming HLL)。暂时没有时间学习,以后再看。

 

posted @ 2020-12-14 20:32  rainforwind  阅读(258)  评论(0)    收藏  举报