注1:本文是之前工作時在團隊內分享的乙個ppt的文字版本.
注2 :我有了新的個人部落格位址
下文中的sqrt表示開根號(sqrt(4)=2),m^n表示m的n次方
基數指的是乙個可重複集合中不重複元素的個數。
給定乙個含有重複元素的有限集合,計算其不重複元素的個數。
應用場景舉例:
簡單來說就是各種uv的計算
常見的實現方式
hash集合 + 計數 或者 bitmap + 計數
缺陷:占用空間過大
基數估計是一類概率演算法,可以在有一定誤差的前提下以遠低於精確計算的時間和空間消耗對基數進行估計
特點它們之間的關係如下圖所示:
作為乙個早期的基數估計演算法,linear counting的空間複雜度方面與簡單bitmap方法是一樣的(但是有個常數項級別的降低,約1/10),都是o(n)。 因此很少單獨使用。目前只在adaptive counting中被混合使用
特點:在基數較小時比較準確
具體演算法如下:
設有一雜湊函式h,其雜湊結果空間有m個值,並且雜湊結果服從均勻分布。
使用乙個長度為m的bitmap,每個bit為乙個桶,均初始化為0
設乙個集合的基數為n,此集合所有元素通過h雜湊到bitmap中,如果某乙個元素被雜湊到第k個位元並且第k個位元為0,則將其置為1。
當集合所有元素雜湊完成後,設bitmap中還有u個bit為0
估計值 n = -mln(u/m)
誤差 = (e^t-t-1)/2n 其中 t = n/m 也就是基數與雜湊空間的比值
標準差 = (sqrt(m)*(et-t-1)0.5)/n
誤差控制,以標準差作為誤差,記容許誤差為e,則 m > (e^t -t -1)/(e*t)^2
例子:n=11(實際數目) m=8(雜湊空間) u=2(0的個數)
估計值=-8*ln(0.25)=11.04
滿桶控制:
如果m比n小太多,則很有可能所有桶都被雜湊到了,此時u的值為0,估計公式就不起作用了(變成無窮大)。
因此m的選擇除了要滿足上面誤差控制的需求外,還要保證滿桶的概率非常小。
m的選取應該遵從:
m > beta(e^t-t-1) 其中 beta=max(5,1/((e*t)^2))
loglog counting 出自**loglog counting of large cardinalities
loglog counting的空間複雜度僅有o(log2(log2(nmax))),所以叫loglog counting
均勻隨機化:與lc一樣,在使用llc之前需要選取乙個雜湊函式h應用於所有元素,然後對雜湊值進行基數估計。h必須滿足如下條件
設a為待估集合(雜湊後)中的乙個元素,由上面對h的定義可知,a可以看做乙個長度固定的位元串(也就是a的二進位制表示).
設h雜湊後的結果長度為l位元,將這l個位元位從左到右分別編號為1、2、…、l:
又因為a是從服從均與分布的樣本空間中隨機抽取的乙個樣本,因此a每個位元位服從如下分布且相互獨立。
p(x=k)=0.5
就是a的每個位元位為0和1的概率各為0.5,且相互之間是獨立的
設ρ(a)為a的位元串中第乙個「1」出現的位置,顯然1≤ρ(a)≤l,這裡我們忽略位元串全為0的情況(概率為1/2^l)。如果我們遍歷集合中所有元素的位元串,取ρmax 為所有ρ(a) 的最大值。
此時我們可以將2^ρmax 作為基數的乙個粗糙估計,即
n 約為 2^ρmax
減小誤差
分桶平均
將雜湊空間平均分成m份,每份稱之為乙個桶
對於每乙個元素,其雜湊值的前k位元作為桶編號, 2^k = m
後l-k個位元作為真正用於基數估計的位元串
桶編號相同的元素被分配到同乙個桶,在進行基數估計時,首先計算每個桶內元素最大的第乙個「1」的位置,設為m[j],然後對這m個值取平均後再進行估計
誤差修正:
誤差分析
當m不太小(不小於64)時:
stderror = 1.30/sqrt(m)
誤差控制:
在應用llc時,主要需要考慮的是分桶數m,而這個m主要取決於誤差。根據上面的誤差分析,如果要將誤差控制在e之內,則:
m > (1.30/e)^2
記憶體使用分析:
假設h的值為32bit,由於ρmax≤32,因此每個桶需要5bit空間儲存這個桶的ρmax,m個桶就是5m/8位元組。
例如基數上限為一億(約227),當分桶數m為1024時,每個桶的基數上限約為227/210=217
因為每個桶需要5bit,需要位元組數就是5×1024/8=640,誤差為1.30/sqrt(1024)=0.040625,也就是約為4%。
llc標準差是漸近組合計數,也就是說,隨著n趨向於無窮大,標準差趨向於1.30/sqrt(m),而不是說n多大時其值都一致為1.30/sqrt(m).
其無偏性也是漸近的,只有當n遠遠大於m時,其估計值才近似無偏。因此當n不太大時,llc的效果並不好。
通過統計分析方法,我們可以得到n具體小到什麼程度我們就不可忍受了,另外就是當n太小時可不可以用別的估計方法替代llc來彌補llc這個缺陷。adaptive counting 及hyperloglog counting都是基於這個思想實現的。
adaptive counting在fast and accurate traffic matrix measurement using adaptive cardinality counting中被提出。
adaptive counting只是簡單將lc和llc組合使用,根據基數量級決定是使用lc還是llc。具體是通過分析兩者的標準差,給出乙個閾值,根據閾值選擇使用哪種估計。
特點:在基數較大時比較準確
分析一下lc和llc的儲存結構,可以發現兩者是相容的,區別僅僅在於llc關心每個桶的ρmax,而lc僅關心此桶是否為空。因此只要簡單認為ρmax值不為0的桶為非空,0為空就可以使用llc的資料結構做lc估計了。
聯立linear counting和loglog counting的誤差
hyperloglog counting的基本思想也是在llc的基礎上做改進, 來自** hyperloglog: the analysis of a near-optimal cardinality estimation algorithm
改進:用調和平均數替代幾何平均數
調和平均數
llc是對各個桶取算數平均數,最終被應用到2的指數上,所以llc取得是幾何平均數。由於幾何平均數對於離群值(例如這裡的0)特別敏感,因此當存在離群值時,llc的偏差就會很大.
當n較小,可能存在較多空桶,而這些特殊的離群值強烈干擾了幾何平均數的穩定性。
估值公式以及誤差:
根據**中的分析結論,與llc一樣hllc是漸近無偏估計,且其漸近標準差為:
se=1.04/sqrt(m)
分段偏差修正:
在hllc的**中,作者在實現建議部分還給出了在n相對於m較小或較大時的偏差修正方案
hyperloglog plus 是google的改進版。來自** hyperloglog in practice: algorithmic engineering of a
state of the art cardinality estimation algorithm
是乙個工程改進版,包括使用fnv64代替原始的32位hash函式,分段偏差修正等工程上的改進,無法嚴格證明
再談基數估計之HyperLogLog演算法
在很久 好像也沒多久,4個月 之前,我曾經寫了一篇和主業無關的有點意思的小文章 基數估計探秘 linear counting與flajolet martin演算法 但是這篇文章講的兩個演算法都已經老掉牙了,實際應用最廣泛的基數估計演算法是hyperloglog hll 演算法。最近筆者基於flink...
通道估計演算法
對通道估計的演算法也有了諸多了解,包括常見的rls lms mmse等,還有最近在研究的壓縮感知通道估計,包括貪婪演算法的mp omp sp以及凸優化演算法中的ls0 ls0 bfgs ls0 fr。總的來說,對於快衰落 通道隨時間變化比較快的,短波無線通道就是 通道通道的估計都需要用到已知序列。在...
排序演算法 基數排序簡介
基數排序也是一種穩定排序演算法,且一般計數排序被用在基數排序過程中。基數排序包括 lsd least significant digital 和 msd least significant digital 兩大類。lsd 基數排序的思想非常直觀 假設乙個陣列的最高位有 d dd 位,那麼依次從低位向...