数据流基本问题--确定频繁元素(二)lossy counting和sticky sampling

我们之前在数据流基本问题--确定频繁元素(一)中提到了频繁元素的一个计算问题(找出出现次数超过m/k的元素),里面的算法返回的结果里肯定包含出现次数超过m/k的元素,但是也可能包含不超过m/k的元素(false positive)。对于这个缺点,必须得进行额外一次的重新扫描,以确定最终答案。我们只允许进行一次的扫描,那么该怎么去做呢?这里我们简单讨论下lossy counting算法和sticky sampling算法。

一、lossy counting算法

其实问题是一样的,这里换个说法来叙述。我们定义两个参数,一个是支持度阈值s,一个是允许错误范围参数)。如果我们想要找出出现频率超过0.1%的元素,则s=0.1%。我们要找到出现次数超过s*m的元素。算法返回的结果里面允许一定的错误,但是允许的范围是*m,也就是说结果中不会出现次数少于(s-)*m的元素。我们一般设为s的1/10。

算法的大致过程很简单,描述如下:将整个数据流切分成多个窗口。

数据流基本问题--确定频繁元素(二)lossy counting和sticky sampling_第1张图片

对于第一个窗口,先统计每个元素及其出现次数,处理结束后,每个元素的出现次数都减一。

数据流基本问题--确定频繁元素(二)lossy counting和sticky sampling_第2张图片

然后继续处理后面的窗口。每处理完一个窗口对保存的所有元素的出现次数都减一。

数据流基本问题--确定频繁元素(二)lossy counting和sticky sampling_第3张图片

算法输出最终计数超过(s-)*m的元素。

如果整个流的长度为m,窗口大小w=1/。这样任意元素元素统计的最大误差是m。该做法空间复杂度为1/ * log(*m)。其实lossy counting的误差比数据流基本问题--确定频繁元素(一)中方法小,是以使用更多空间作为代价的。

二、sticky sampling算法

该算法的思想就是通过采样来对频繁元素进行估计。该算法比lossy counting多了一个参数,错误率(很小的实数,比如0.01%)。算法中涉及到一个数据结构S,里面的每条记录的形式为,其中为元素x出现次数的估计。

初始状态S为空,采样率r设为1。用r采样判断是否选择某个元素是指以1/r的概率进行选取。对于到来的每一个元素e,如果e已经存在于S中,我们只需要对加一。否则我们对该元素进行采样,如果该元素被选择,则向S中添加新的记录。如果没有被选中,我们忽略e并接着处理后续的元素。

对于采样率r一般随数据流的不断增加而变化。设t=。在前2t个元素,r=1;后面2t个元素,r=2;后面4t个元素,r=4,依次类推。整个过程就像一轮一轮一样,每轮的r值固定。每次当r发现变化之后,我们就扫描S中的记录。对于每条记录,我们连续投掷一个硬币(出现正面和反面的概率相等)直到出现正面,每次出现反面时我们对减一,如果为0则将该记录从S中删去。

sticky sampling保证在满足较高概率1-的情况下,元素出现次数最多小于真实值*m,结果中不会出现对元素估计少于(s-)*m。可以证明,算法运行过程中S中最多包含条记录,这里计算的就是算法的空间复杂度,这里可以发现算法的空间复杂度和数据流的长度m是无关的。

参考资料:

《Approximate Frequency Counts over Data Streams》

你可能感兴趣的:(数据流算法)