深入解析Bloom Filter(上)

avuj1787 8年前發布 | 8K 次閱讀 布隆過濾器 算法

來自: http://www.yebangyu.org/blog/2016/01/23/insidethebloomfilter/

本文將介紹:

  • Bloom Filter和它的變形與拓展
  • Bloom Filter的使用場景
  • Bloom Filter的詳細數學分析

提出問題

Google的爬蟲每天需要抓取大量的網頁。于是就有一個問題:每當爬蟲分析出一個url的時候,是抓呢,還是不抓呢?如何知道這個url已經爬過了?

這個問題,歸納抽象后可以定義為:

給定一個集合S(注意,這里的集合是傳統意義上的集合:元素彼此不同。本文不考慮multiset),給定一個元素e,需要判斷$e\in S$ 是否成立。(學術界一般稱為membership問題)

分析問題

都有哪些方案可以解決這個問題?

一種簡單的想法是把url存儲在一個哈希表中,每次去表里look up下判斷是否存在。假如每個url占用40B,那么10億條url將占用大概30多GB的內存!Can this be more space efficient ?

解決問題

我們可不可以不存url本身?這樣子所需空間就會大大減少了。于是我們想到一個很經典的做法:bitmap(位圖)。將集合S中的url哈希到bitmap上,給定一個url,只需要將它hash,得到它在bitmap的下標,檢查該位置是否為1即可。

這樣做空間是省了,可是也產生了一個問題:由于沖突(碰撞),不是集合S中的元素也可能被哈希到值為1的位置上,導致誤報。

給定一個元素e,如果實際上$e\notin S$ 而被判為 $e\in S$,那么我們稱e是false positive(偽正例。順便說一句,false positive等的分析在machine learning的classification任務里評價model時非常重要)。

如何降低false positive的概率呢?Bloom Filter的想法是使用多個獨立的哈希函數。

Standard Bloom Filter

在傳統的Bloom Filter中,我們有:

集合S:其大小為m。也就是說,集合中有m個不同元素。

可用內存B:B被當成位數組bitmap來使用,大小為n。(有n個bit)。

哈希函數:有k個獨立的、均勻分布的哈希函數。

Bloom Filter的做法是:初始時,所有比特位都初始化為0。對于集合中的每個元素,利用k個哈希函數,對它哈希得到k個位置,將bitmap中的對應的k個位置置為1。

給定一個元素e,為了判斷它是否是集合中的元素,也利用該k個函數得到k個位置,檢查該k個位置是否都為1,如果是,認為$e\in S$,否則認為$e\notin S$。

不難看出,如果$e\in S$,那么Bloom Filter肯定會正確判斷出$e\in S$,但是它還是可能產生false positive。那么,如何分析false positive的概率呢?

false positive發生時,表示哈希該元素后得到的k個位置都為1。這個概率大概為:

$P\approx p_1^k$

其中$p_1$代表某位為1的概率,它等于:

$p_1 = 1 - p_0$

對于$p_0$,表示某個特定的比特位為0。什么時候該位才為0呢?也就是說m個元素各自經過k次哈希得到km個對象,沒有一個對象定位到了該位置。某個對象定位到該位置的概率為$\frac{1}{n}$,因此我們可以得到:

$p_0 = (1 - \frac{1}{n})^{mk}$

分析$p_0$。在實際應用中,n一般很大,根據重要極限公式,我們不難得到:

$p_0 = (1 - \frac{1}{n})^{mk} = (1-\frac{1}{n})^{-n{\frac{mk}{-n}}} \approx e^{-\frac{mk}{n}} $

代入到最上面的那個式子,我們不難得到:

$P \approx ({1 - e^{-\frac{mk}{n}}})^{k}$

當k為何值時,P取得最小,false positive possibility最低呢?

令 $f(k) = ({1 - e^{-\frac{mk}{n}}})^{k}$

$ln(f(k)) = kln({1 - e^{-\frac{mk}{n}}})$

$\frac{f\prime(k)}{f(k)} = ln({1 - e^{-\frac{mk}{n}}}) + k(\frac{1}{1 - e^{- \frac{mk}{n}}})(- e^{-\frac{mk}{n}})(\frac{-m}{n})$

$f\prime(k) = f(k)(ln({1 - e^{-\frac{mk}{n}}}) + k(\frac{1}{1 - e^{- \frac{mk}{n}}})(- e^{-\frac{mk}{n}})(\frac{-m}{n}))$

看起來夠復雜了,然而別怕!!!

令$f\prime(k) = 0$ , 我們有(注意到$f(k) > 0$ 恒成立):

$ln({1 - e^{-\frac{mk}{n}}}) + k(\frac{1}{1 - e^{- \frac{mk}{n}}})(- e^{- \frac{mk}{n}})(\frac{-m}{n}) = 0$

作代換,令$\lambda = e^{-\frac{mk}{n}}$ 則 $k = \frac{-nln\lambda}{m}$,代入上式,得到

$(1-\lambda)ln(1-\lambda) = \lambda ln\lambda$

因此$\lambda = \frac{1}{2}$ , $k = \frac{n}{m}ln2$

也就是說,當n和m固定時,選擇$k = \frac{n}{m}ln2$ 附近的一個整數,將使false positive possibility最小。

工程實現時,我們需要k個哈希函數或者哈希函數值。如何構造和獲得k個獨立的哈希函數呢?這篇 論文 提出,只需要兩個獨立的哈希函數hf1和hf2即可。那么可以通過如下方式獲得k個哈希函數值:

hash value = hf1(key) + i*hf2(key)

其中i=0、1、2…k-1

Counting Bloom Filter

除了存在false positive這個問題之外,傳統的Bloom Filter還有一個不足:無法支持刪除操作(想想看,是不是這樣的)。而Counting Bloom Filter(CBF)就是用來解決這個問題的。

在CBF中,維護的不是單純的標示0或者1的比特位,而是若干計數器counter。對于集合中的每個元素,利用k個哈希函數,對它哈希得到k個位置,將對應的k個位置上的k個counter都加1。刪除時,只需要把k個counter都減1即可。

那么,這個counter應該占用幾位呢?分配太多,浪費空間;分配太少,容易溢出。通過下面的分析,我們可以知道,實際使用時,4位足矣。

考察(是考察,不是考查。這兩個詞有什么區別?)某個位置,該位置的計數器counter的值$\xi$

$P(\xi = c) \approx \binom{mk}{c} {(\frac{1}{n})}^{c}({1-\frac{1}{n}})^{mk-c} = B(km,\frac{1}{n})$

這個式子有點點復雜(當然,可以用斯特林公式近似一下),然而回憶下概率論里的知識:若二項分布B(n,p)里n很大,p很小時,二項分布的極限近似分布是泊松分布$P(\lambda=k) = \frac{\lambda^k}{k!}{e}^{-\lambda}$,其中$\lambda=np$,因此:

$P(\xi = c) \approx \binom{mk}{c} {(\frac{1}{n})}^{c}({1-\frac{1}{n}})^{mk-c} \approx \frac{({\frac{km}{n}})^{c}}{c!}{e}^{-{\frac{km}{n}}}$

令$k = \frac{n}{m}ln2$,代入,我們得到

$P(\xi >16) \approx \frac{(ln2)^{16}}{16!} * \frac{1}{2} < \frac{1}{16!} = \frac{1}{20922789888000}$

也就是說,選擇4位來存counter在實際情況中已經足矣,發生溢出的概率極小。

本文小結

總結下,Bloom Filter可以用在什么地方,或者說,在什么場景下,你應該想到這種技術:

1,回答是或者不是的問題。你需要判斷一個元素是否屬于某個集合,僅僅這樣。你不應該要求更多。如果你想獲得該元素對應的value或者還有其他payload,那么bloom filter不適合你,你需要哈希表。

2,允許false positive。也就是說,發生false positive不應該是致命的。比如說,搜索引擎的爬蟲里,如果url不是set的元素,卻被bloom filter過濾了,那么頂多就是不抓它而已,沒啥特別大的損失。

3,空間敏感。作為一種概率數據結構,Bloom Filter不存儲原始數據(比如說url),這也是它為什么space efficient的本質原因。

有了Standard Bloom Filter和Couting Bloom Filter,似乎可以滿足絕大多數需求了,然而,這里面還是有問題。什么問題?請看下集。

</div>

 本文由用戶 avuj1787 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!