基數估計算法簡介


基數估計算法簡介

注1:本文是之前工作時在團隊內分享的一個PPT的文字版本.
注2 :我有了新的個人博客地址

下文中的sqrt表示開根號(sqrt(4)=2),m^n表示m的n次方

什么是基數(Cardinality)

基數指的是一個可重復集合中不重復元素的個數。

什么是基數計算

給定一個含有重復元素的有限集合,計算其不重復元素的個數。

應用場景舉例:

  • 某家店鋪今天有多少不同用戶訪問
  • 某家店鋪今天接待了多少不同買家

簡單來說就是各種UV的計算

常見的實現方式

Hash集合 + 計數 或者 BitMap + 計數

缺陷:占用空間過大

什么是基數估計算法

基數估計是一類概率算法,可以在有一定誤差的前提下以遠低於精確計算的時間和空間消耗對基數進行估計

特點

  • 有誤差
  • 時間復雜度和空間復雜度僅與誤差和基數上限有關
  • 易於合並

有哪些基數估計算法

  • Linear Counting
  • LogLog Counting
  • Adaptive Counting
  • HyperLogLog Counting
  • HyperLogLog++ Counting

它們之間的關系如下圖所示:

Linear Counting

Linear Counting是在1990年的一篇論文
A linear-time probabilistic counting algorithm for database applications 中被提出。

作為一個早期的基數估計算法,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 出自論文Loglog Counting of Large Cardinalities

Loglog Counting的空間復雜度僅有O(log2(log2(Nmax))),所以叫LogLog Counting

算法前提

均勻隨機化:與LC一樣,在使用LLC之前需要選取一個哈希函數H應用於所有元素,然后對哈希值進行基數估計。H必須滿足如下條件

  • H的結果具有很好的均勻性,無論原始集合元素的值分布如何,其哈希結果的值幾乎服從均勻分布

  • 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

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

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

HyperLogLog plus 是Google的改進版。來自論文 HyperLogLog in Practice: Algorithmic Engineering of a
State of The Art Cardinality Estimation Algorithm

是一個工程改進版,包括使用FNV64代替原始的32位Hash函數,分段偏差修正等工程上的改進,無法嚴格證明

Java中的相關實現


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM