大資料流的線上Heavy Hitters演算法(下篇):基於略圖的方法
Continue...
之前有好幾篇分上下篇寫的文章都鴿了,慚愧慚愧。為了不食言,今天繼續聊Heavy Hitters(頻繁項)演算法之基於略圖(Sketch)的方法。時間緊張且限於水平,寫得簡單些,看官勿怪。
什麼是略圖
顧名思義,略圖(Sketch)就是能夠大致準確地描述一份資料集的摘要。當資料量非常大時,往往不能直接放入記憶體中,普通的查詢樹、雜湊表等受制於資料規模,自然也就沒有用武之地了。然而,略圖的出現以精準度作為trade-off換來了時間、空間效率的極大提升,也使得解決大資料上的Heavy Hitters以及其他很多問題成為可能。
概率性資料結構(probabilistic data structure)有不少都採用了略圖的思想,筆者很久之前講過的
Count-Min Sketch
Count-Min Sketch的論文發表於2004年,其資料結構由兩部分組成:
- 一個寬度為w,深度為d(即d行w列)的二維整數陣列,初始化為全0;
- d個互相獨立的雜湊函式h1...hd,其雜湊空間均為[1...w]。
接下來觀察資料流,當資料流中元素j出現時(可以出現1次,也可以連續出現c次),將j分別用雜湊函式h1
那麼如何估計一個元素j的大致出現頻率f[j]呢?答案是直接取元素j對應的所有雜湊桶中,計數值最小的那一個。即:
f[j] = mink CMS[k][hk(j)]
當然,為了保證一定的精準度,w和d的值也不是隨便取的。定義精度引數為ε,誤差概率引數為δ(兩者都是很小的正數),那麼就有:
w = 2/ε, d = log 1/δ
ε、δ兩個引數之間有如下的關係:
P{ f[j] <= f[j] + ε||f||1
} >= 1 - δ
翻譯成人話:在至少為1 - δ的概率下, Count-Min Sketch對任意一個元素j估計的出現頻率與其真實頻率的誤差小於所有元素真實頻率之和的ε倍。這個結論可以用馬爾可夫不等式來證明,筆者數學不怎麼樣,就不班門弄斧了。
容易得知,由於雜湊衝突的存在,Count-Min Sketch給出的頻率估計肯定是偏大的(即f[j] >= f[j])。在輸入資料量足夠多的情況下,選擇最小的頻率計數值就意味著雜湊衝突最少,亦即更接近真實的頻率值。反過來,它對於很少出現的元素,表現就會比較差。
話說回來,如何用Count-Min Sketch解決Heavy Hitters問題呢?答案就比較直白了——使用K個元素的最小堆維護Top-K,每更新一個元素的計數,就同時更新到最小堆,並隨時移除頻率過小的元素。具體操作方法參見筆者之前介紹PriorityQueue的文章的結尾。
Count-Min Sketch在現實中的應用也很廣泛。在筆者所知的開源框架裡,Spark在spark-sketch子模組中實現了包括Count-Min Sketch在內的多種略圖結構,並應用在CountMinSketchAgg聚合函式以及DataFrame的資料統計中。PostgreSQL也有一個Count-Min Sketch外掛,專門用於近似計算Top-K。
Count Sketch
Count Sketch的論文發表於2002年,比Count-Min Sketch還要早,本質上是Count-Min Sketch的一般化形式。除了w*d的二維陣列和d個雜湊函式之外,還有另外一組雜湊函式g1...gd,且它們的雜湊空間只有{1, -1}兩個值。另外,g1...gd取{1, -1}的分佈必須是隨機且均勻的,也就是說E[g(j)]=0。
當資料流中元素j出現c次時,將j分別用雜湊函式h1...hd對映到二維陣列中每一行的對應位置,並將該位置的值加上c*g(j),如下圖所示。
g1...gd雜湊函式是Count Sketch與Count-Min Sketch的最大不同點,它的存在可以部分抹去Count-Min Sketch中的只加操作帶來的正誤差,因此估算f[j]時不必再取元素j對應的所有雜湊桶中計數值最小的那一個了。相對地,我們取中位數,即:
f[j] = medianj CS[k][hk(j)] * gk(j)
Count Sketch的ε、δ兩個引數與估計誤差之間有如下的關係(可以藉助切比雪夫不等式證明):
P{ f[j] - ε||f-j||2 <= f[j] <= f[j] + ε||f-j||2 } >= 1 - δ
由上可知,Count-Sketch給出的頻率估計有可能偏大也有可能偏小,但是它用更多的空間(w ~ O(1/ε2))換來了比Count-Min Sketch更嚴格的誤差界限。
使用Count Sketch解決Heavy Hitters問題的思路與Count-Min Sketch相同,就不再贅述了。
The End
還有一大堆其他的事情要搞,晚安吧各位。