布隆过滤器的推导

bloom filter

intro

布隆过滤器是一种很有意思的数据结构,它的用途是检测某个元素是否在一个集合中。

首先,有一个数组,它的元素全部是0,然后共有m个坑:

我现在有一个集合 S = { x , y , z } S=\left\{ x,y,z \right\} S={x,y,z},对于每一个元素,通过3个hash函数,将其打到数组上,打中的位置设置为1。

比如 x x x,三次hash后,数组上就会有3个位置变为1(蓝色线条)。

至于hash函数,你可以认为它对 x x x做了处理,最后模上数组的长度得到一个下标。

注意,元素hash后可能打中同一个坑,这点不必惊奇。当m的值(也就是数组的长度)越来越大,这种情况的概率就会越来越小。

现在我来了一个 w w w,我要问: w w w在不在 S S S中?

w w w也三次hash一下:

  • 如果有打中0的情形,那么,它肯定不在 S S S中。
  • 如果打中的全部是1,那么它很有可能在 S S S中,也就是说,可以判定它在 S S S中,并带有一定的错误概率。

more general

我们的根本目的是减少错误概率。

现在考虑一般情况。

  • 数组的长度为 m m m
  • 集合为 S = { x 1 , x 2 , … , x n } S=\left\{ x_1,x_2,\dots,x_n \right\} S={x1,x2,,xn},有 n n n个元素
  • hash函数有 k k k个: h 1 , h 2 , … , h k h_1,h_2,\dots,h_k h1,h2,,hk 0 ≤ h i ( x j ) < m ( 1 ≤ i ≤ k , 1 ≤ j ≤ n ) 0 \le h_i(x_j)\lt m(1 \le i \le k, 1 \le j \le n) 0hi(xj)<m(1ik,1jn),换句话说,每个元素 x i x_i xi的每次hash的下标都落在数组内
  • hash函数产生的下标是等概率均匀分布的,不是说全部挤在前面或者某一个地方

好,现在我们考虑一个元素(比如 x 1 x_1 x1)的插入(占坑)。

经过一次hash后,某个坑为1的概率为:

1 m \frac{1}{m} m1

某个坑为0的概率是:

1 − 1 m 1-\frac{1}{m} 1m1

k k k个hash函数过后,某个坑依旧为0的概率是:

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

因为 lim ⁡ m → + ∞ ( 1 − 1 m ) − m = e \lim\limits_{m\to+\infty}(1-\frac{1}{m})^{-m}=e m+lim(1m1)m=e,所以

lim ⁡ m → ∞ ( 1 − 1 m ) k = lim ⁡ m → ∞ [ ( 1 − 1 m ) − m ] − k m = e − k m \lim\limits_{m\to\infty}(1-\frac{1}{m})^k=\lim\limits_{m\to\infty}[(1-\frac{1}{m})^{-m}]^{-\frac{k}m{}}=e^{-\frac{k}{m}} mlim(1m1)k=mlim[(1m1)m]mk=emk

我们会假设数组的长度 m m m无穷大,所以上面的式子是成立的。

完成了一个元素的插入后,现在我插入 n n n个元素

n n n个元素插入后,某个坑依旧为0的概率是:

e − n k m e^{-\frac{nk}{m}} emnk

于是某个坑为1的概率是:

1 − e − n k m 1-e^{-\frac{nk}{m}} 1emnk

现在我来了一个元素 y y y y y y并不在 S S S

y y y经过 k k k个hash函数 后,全部打到了标记为1的坑,这个概率是:

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

好了,我们找到了最终的函数。

目标:使 f = ( 1 − e − n k m ) k f=(1-e^{-\frac{nk}{m}})^k f=(1emnk)k

最小。


f = e ln ⁡ ( 1 − e − n k m ) k = e k ln ⁡ ( 1 − e − n k m ) f=e^{\ln(1-e^{-\frac{nk}{m}})^k}=e^{k\ln(1-e^{-\frac{nk}{m}})} f=eln(1emnk)k=ekln(1emnk)


g = k ln ⁡ ( 1 − e − n k m ) g=k\ln(1-e^{-\frac{nk}{m}}) g=kln(1emnk)

问题转化为求 g g g的最小值。

∂ g ∂ k = ln ⁡ ( 1 − e − n k m ) + ( 1 1 − e − n k m ) ( − e − n k m ) ( − n m ) ( k ) \frac{\partial g}{\partial k}=\ln(1-e^{-\frac{nk}{m}})+(\frac{1}{1-e^{-\frac{nk}{m}}})(-e^{-\frac{nk}{m}})(-\frac{n}{m})(k) kg=ln(1emnk)+(1emnk1)(emnk)(mn)(k)

∂ g ∂ k = 0 \frac{\partial g}{\partial k}=0 kg=0

同时,令

e − n k m = p e^{-\frac{nk}{m}}=p emnk=p

于是

n m = ln ⁡ p − k \frac{n}{m}=\frac{\ln p}{-k} mn=klnp

那么

ln ⁡ ( 1 − p ) + ( 1 1 − p ) ( p ) ( ln ⁡ p − k ) ( k ) = ln ⁡ ( 1 − p ) − p 1 − p ln ⁡ p = 0 \ln(1-p)+(\frac{1}{1-p})(p)(\frac{\ln p}{-k})(k)=\ln(1-p)-\frac{p}{1-p} \ln p=0 ln(1p)+(1p1)(p)(klnp)(k)=ln(1p)1pplnp=0

整理一下:

( 1 − p ) ln ⁡ ( 1 − p ) = p ln ⁡ p (1-p)\ln (1-p)=p \ln p (1p)ln(1p)=plnp

得到

p = 1 2 p=\frac{1}{2} p=21

于是

k = m n ln ⁡ 2 k=\frac{m}{n} \ln 2 k=nmln2

k , m , n k,m,n k,m,n满足 k = m n ln ⁡ 2 k=\frac{m}{n} \ln 2 k=nmln2能够使得 f f f最小。

也就是说,如果数组长度比上元素个数为8的话( m n = 8 \frac{m}{n}=8 nm=8),那么hash函数的个数最好有 8 ln ⁡ 2 ≈ 5.45 8\ln 2 \approx5.45 8ln25.45个(你可以取个整)。

这是一个令人愉快的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值