BloomFilter, Count-Min Sketch算法

项目github地址:bitcarmanlee easy-algorithm-interview-and-practice
欢迎大家star,留言,一起学习进步

1.bloom filter

布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

2.两种错误率FP/FN

FP = A false positive error, or in short a false positive, commonly called a “false alarm”, is a result that indicates a given condition exists, when it does not.

FN = A false negative error, or in short a false negative, is a test result that indicates that a condition does not hold, while in fact it does.

在bloom filter中,FP是集合里没有某元素,查找结果是有该元素。FN是集合中有某元素,查找结果是没有该元素。

在bloom filter中,FP 会随着 BF 中插入元素的数量而增加——极限情况就是所有 bit 都为 1,这时任何元素都会被认为在集合里。而FN则为0,如果某元素在集合中,则一定能找到该元素。

3.FP的推导

假设哈希函数以相等的概率选择位数组中的位置。如果 m 是位数组中的比特数,则在插入元素期间某一特定比特位不被某个哈希函数设置为 1 的概率是:

1 − 1 m 1- \frac{1}{m} 1m1
假设有k个哈希函数,则通过 k 个哈希函数都未将该位设置为 1 的概率是
( 1 − 1 m ) k (1- \frac{1}{m}) ^ k (1m1)k

那么,如果我们插入了 n 个元素,某个位仍然为 0 的概率就是:

( 1 − 1 m ) n k (1- \frac{1}{m}) ^ {nk} (1m1)nk

因此这一位的值为 1 的概率就是:

1 − ( 1 − 1 m ) n k 1 - (1- \frac{1}{m}) ^ {nk} 1(1m1)nk

那么,BF 的误判率是怎么得出的?前面提到,我们主要关注 FP,即集合里没有某元素,查找结果是有该元素。

现在我们要判断一个元素是否在集合中,假设这个元素本不在集合中,理论上来讲,经过 k 个哈希函数计算后得到的位数组的 k 个位置的值都应该是 0,如果发生了误判,即这 k 个位置的值都为 1,这个概率如下:

( 1 − ( 1 − 1 m ) k n ) k = ( 1 − e − k n m ) k (1 - (1- \frac{1}{m}) ^ {kn}) ^ k = (1- e^{-\frac{kn}{m}})^k (1(1m1)kn)k=(1emkn)k

4.stream lib中的bloom filter

    public void test2() {
        Filter filter = new BloomFilter(1000, 0.01);
        filter.add("abc");
        filter.add("def");
        filter.add("g");
        boolean result = filter.isPresent("123");
        System.out.println("result is: " + result);
    }

Filter filter = new BloomFilter(1000, 0.01); 1000是在构建BitSet时跟bit数组位数有关的参数,0.01是错误率。

5.Count-Min Sketch算法

CountMinSketch 是一种“速写”算法,能够使用较小的空间勾勒出数据集内各类事件的频次。比如,我们可以统计出当前最热门的推特内容,或是计算网站访问量最大的页面。当然,这一算法同样会牺牲一定的准确性。

CountMinSketch算法的流程:
1.选定d个hash函数,开一个 dxm 的二维整数数组作为哈希表
2.于每个元素,分别使用d个hash函数计算相应的哈希值,并对m取余,然后在对应的位置上增1,二维数组中的每个整数称为sketch
3.要查询某个元素的频率时,只需要取出d个sketch, 返回最小的那一个(其实d个sketch都是该元素的近似频率,返回任意一个都可以,该算法选择最小的那个)

6.Count-Mean-Min Sketch

Count-Min Sketch算法对于低频的元素,结果不太准确,主要是因为hash冲突比较严重,产生了噪音,例如当m=20时,有1000个数hash到这个20桶,平均每个桶会收到50个数,这50个数的频率重叠在一块了。Count-Mean-Min Sketch 算法做了如下改进:
1.来了一个查询,按照 Count-Min Sketch的正常流程,取出它的d个sketch
2.对于每个hash函数,估算出一个噪音,噪音等于该行所有整数(除了被查询的这个元素)的平均值
3.用该行的sketch 减去该行的噪音,作为真正的sketch
4.返回d个sketch的中位数

class CountMeanMinSketch {
    // initialization and addition procedures as in CountMinSketch
    // n is total number of added elements
    long estimateFrequency(value) {
        long e[] = new long[d]
        for(i = 0; i < d; i++) {
            sketchCounter = estimators[i][ hash(value, i) ]
            noiseEstimation = (n - sketchCounter) / (m - 1)
            e[i] = sketchCounter – noiseEstimator
        }
        return median(e)
    }
}

Count-Mean-Min Sketch算法能够显著的改善在长尾数据上的精确度。

参考文献
1.https://zh.wikipedia.org/wiki/%E5%B8%83%E9%9A%86%E8%BF%87%E6%BB%A4%E5%99%A8
2.http://shzhangji.com/cnblogs/2017/08/27/an-introduction-to-stream-lib-the-stream-processing-utilities/
3.https://soulmachine.gitbooks.io/system-design/content/cn/bigdata/frequency-estimation.html

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值