概率/近似计数 [完整概述]

455 阅读9分钟

Probabilistic / Approximate Counting [Complete Overview]

在这篇文章中,我们将介绍和探讨 概率论的算法在这个领域中,我们将深入介绍和探索不同的算法,如Morris算法、HyperLogLog、LogLog和其他算法。

内容表

  1. 概率/近似计数算法的概述

  2. 计数的问题陈述

  3. 近似计数算法(莫里斯算法)
    3.1 概述
    3.2 工作
    3.3 应用
    3.4 复杂性

  4. 超日志算法
    4.1 概述
    4.2 日志算法
    4.3 工作
    4.4 改进和差异 4.5
    应用 4.6

    复杂性

  5. 参考文献

概率/近似计数算法的概述

概率/近似计数算法允许人们使用少量的内存来计算大量的事件。

当一个程序、应用程序等的内存方面的使用和复杂性必须是最小的时候,这些类型的算法就特别有用。

在这篇文章中,我们将探讨两种概率/近似计数算法,它们是。

  1. 近似计数或莫里斯算法
  2. LogLog算法
  3. 超日志算法
  4. 进一步的改进

计数的问题陈述

在大多数概率算法中,计数过程通常是类似的。
让我们假设我们有一个哈希函数,表示为。

fun hash(x: records): scalar range[0 ... 2ᴸ-1] 。

其中长度用L表示。

该函数将记录(传入)转化为均匀分布在长度为L的二进制字符串标量范围内的整数。
可以看到,如果hash(x)的值是均匀分布的,那么0ᵏ1 ...的模式出现的概率是2ᵏ-¹。主要的想法是在一个长度为L的向量BITMAP(BITMAP[0 ... L-1])中记录对上述模式出现的观察。

我们假设要确定的列表/多集的cardinality是M,那么我们以下的操作就必须要完成这个目标。

1. for i from 0 to L-1 do:
    1.1. put BITMAP[i] = 0
2. for all x in M do:
    2.2. put index = ρ(hash(x))
    2.3. if BITMAP[index] = 0 do:
        2.3.1. put BITMAP[index] = 1

上述算法中提到的另一个函数/方法是ρ(i),它基本上代表i的二进制表示中最不重要的1位的位置。

在BITMAP向量中得到的最终值被用作计数操作的锚点。

请记住,大多数高级算法都有自己对算法的修改,然而,基础大多保持不变。

3.近似计数算法(莫里斯算法

3.1 概述

该算法 近似计数算法的发明者是 罗伯特-莫里斯在1977年发明的。

该算法利用了 概率技术来递增 计数器以便对事件进行计数,正因为如此,它的精确性并不是绝对的,尽管它确实提供了一个相当好的对真实值的估计,同时提供了一个最小但相当稳定的相对误差。
这个算法源于一次莫里斯不得不在一个8位寄存器中计算大量事件的时候。该
算法被认为是流媒体
算法
的基础算法之一

3.2 工作

创建一个有效的概率/近似计数器的简单而明显的方法是计算每一个交替发生的事件。

然而,在莫里斯的算法中,我们不是跟踪事件的总数n或n的某个常数倍,而是在寄存器中存储的值是(1+n)的对数值。

计数器是如何决定哪个事件应该被计算的呢?其中一个方法是利用掷硬币的技术,这相对简单。以下是它的工作原理。

我们抛出一枚硬币,如果结果是正面,那么我们就增加计数器,否则就任其发展。

计数器将代表一个数量级的估计值,即相对于一些理解的参考值的对数的近似值,即实际计数。当计数器运行时,只存储用于增加计数器的概率技术的指数。这样做是为了节省空间。

例如,基数为2时,计数器可以估计出计数为1、2、4、8、16、....,依此类推。当基数为3时,计数器可以估计计数为1、3、9、27、81、....,等等。

为了从9增加到27,要产生一个伪随机数,使其概率为¼(0.25),在计数器中产生一个正的变化。如果是这样,那么计数器就会被递增,否则计数器就会保持在9。

下表以3为基数,展示了计数器的工作和潜在值。

计数器的二进制值估计值实际计数的数值范围预期值
010,或初始值0
131,或更多6
1092,或更多24
11273,或更多78
100814,或更多240
1012435,或更多726

当计数器的值为100(二进制值),相当于指数为4(相当于100的十进制),那么估计的计数为3^4,即81。实际的增量事件计数是4的概率相当低(1 ***¹₂₇=¹⁄₇₂₉)。增量事件的实际计数可能在81左右,但也可能是任意的高。

3.3 应用

该算法可用于调查大型数据集/数据流的模式。它在数据压缩、视觉和声音识别以及其他人工智能应用中特别有用。

3.4 复杂度

让我们假设,我们必须通过掩盖使用莫里斯的算法来计算到n。我们知道,它将上升到 **O(logn)**(记住,计数器只保留指数以节省空间),因此,从0数到n需要的总位数 **O(logn)**将变成 **O(log(logn))**.

因此,莫里斯算法的总体空间复杂度为 **O(log(logn))**.

4.超日志算法

4.1 概述

Hyperloglog算法,是对早期算法的进一步扩展。 日志算法的进一步扩展。这两种算法的主要目标仍然相同,即估计给定列表/集/流中唯一/不同项目的数量。超日志算法确定一个列表/集/流中的cardinality或uniqueness(唯一元素的数量)。
像大多数概率算法一样,超日志算法在完成同样的任务时使用的内存或空间也明显少于其对应的算法,主要是因为该算法主要强调在不影响其性能和主要目标的情况下节省内存和空间。
让我们先简单了解

一下

日志算法,以便我们对超

日志

算法有更好的理解。

4.2 日志算法

Loglog是一种概率算法,利用散列函数来随机化数据,然后将其转换为类似于随机二进制数据的形式。然后,散列的数据集被该算法改成了心率估计值。

一般来说,loglog算法利用n个小字节的辅助内存来估计一个列表中唯一元素的数量,其精度为1/√n。

它在很多情况下都很有用,比如快速计算一本书中不同的字数和它们的数量等等。
就空间复杂度而言,如果n是算法必须操作的范围,loglog算法会消耗**O(log(logn))** 位存储。

这种算法有许多优化版本,如 超级loglog, 超loglog,等等。

4.3 工作

与hyperloglog起源的算法(loglog算法)一样,它也利用了一个散列函数,应用于给定集合/列表中的每一个元素,以获得一组均匀分布的随机数,其cardinality与原始集合相同。

然而,仅仅这样做来获得一个集合的cardinality将导致一个大的方差。为了解决这个问题,超对数算法进一步将集合细分为不同的子集,之后计算每个子集中数字的最大前导零数。在这一操作之后,谐波平均数被用来将所有子集的计算估计值合并为一个合并子集的心数估计值。

超对数算法有三个主要操作,其数据存储在一个称为寄存器的计数器阵列P中,其大小为p,在初始状态下被设置为0。

**1> 添加操作。**该操作用于向集合添加一个新元素。它包括用哈希函数h计算输入数据d的哈希值,得到前b位(b=log2p)。通过加1得到要修改的寄存器的地址。剩余的比特用于计算ρ(w),它返回在索引方面出现在最左边的1的位置(以二进制形式)。寄存器的当前值和ρ(w)之间的最大值被选为寄存器的新值。

2>计数操作。这个操作是用来获得集合的cardinality的。计算p个寄存器的谐波平均值,然后用一个常数得出计数(cardinality)的估计值E。

3> 合并操作。该操作用于将两个集合合并或连接在一起。例如,如果我们有两个不同的集合U1和U2使用超对数算法,那么合并操作将获得每对寄存器的最大值,即从1到p的j。
Merge(U1, U2)[j] = max(U1[j], U2[j])

4.4 改进与不同之处

尽管HyperloglogLoglog算法的总体复杂度大致相同,但它们之间仍有一些明显的区别,因为Hyperloglog只是loglog算法的一个改进和更有效的版本。

  • Hyperloglog算法将集合进一步划分为子集,然后对其进行进一步的操作。这样做主要是为了确保方差(在获得cardinality时)保持最小。这提高了该算法的效率和准确性。

  • 超日志使用调和平均数来估计一个给定的列表/集的cardinality,而loglog算法使用正常平均数。

  • Hyperloglog算法的标准误差估计是(1.04/√n),而loglog算法的标准误差是(1.30/√n),其中n是桶的数量。这种差异虽然不是很明显,但当算法用于大数据集时(通常是这样),这种差异就会发挥作用。

4.5 应用

超对数算法的主要应用是为一个给定的集合估计准确的cardinality,同时非常节省空间。
它可以用于有非常大的数据集的应用或软件中,也可以用于各种形式的图统计。

4.6 复杂度

Hyperloglog算法的相对误差一般为1/√p,空间复杂度为
**O(ε⁻²log(logn) + logn)**
,其中n是集合的cardinality,p是寄存器的数量。考虑到

主要的操作,添加操作取决于主哈希函数输出的大小,因此其运行时间为**O(1)** ,因为它具有固定性。由于计数和合并操作实际上取决于寄存器(p)的大小,它们的运行时间为**O(p)** 。然而,如果寄存器的数量是固定的,那么这两个操作的运行时间也会变得恒定。

因此,超loglog算法的总体空间复杂度为 **O(log(logn))**

参考文献

  • "Philippe Flajolet和G.Nigel Martin"数据库应用的概率计数算法",载于《计算机和系统科学杂志》1985年10月。