Un HyperLogLog è una struttura di dati probabilistica . Conta il numero di elementi distinti in un elenco. Ma rispetto a un modo semplice di farlo (avere un set e aggiungere elementi al set) lo fa in modo approssimativo.
Prima di vedere come funziona l'algoritmo HyperLogLog, bisogna capire perché ne hai bisogno. Il problema con un modo semplice è che consumaO(distinct elements)
spazio. Perché qui c'è una grande notazione O anziché solo elementi distinti? Questo perché gli elementi possono avere dimensioni diverse. Un elemento può essere 1
un altro elemento "is this big string"
. Quindi se hai un enorme elenco (o un enorme flusso di elementi) ci vorrà molta memoria.
Conteggio probabilistico
Come si può ottenere una stima ragionevole di un numero di elementi unici? Supponiamo di avere una stringa di lunghezza m
che consiste {0, 1}
con uguale probabilità. Qual è la probabilità che inizi con 0, con 2 zeri, con k zeri? Lo è 1/2
, 1/4
e 1/2^k
. Ciò significa che se hai incontrato una stringa con k
zeri, hai guardato approssimativamente attraverso gli 2^k
elementi. Quindi questo è un buon punto di partenza. Avere un elenco di elementi che sono equamente distribuiti tra0
e 2^k - 1
puoi contare il numero massimo del più grande prefisso di zeri nella rappresentazione binaria e questo ti darà una stima ragionevole.
Il problema è che l'ipotesi di distribuire uniformemente numeri da 0
t 2^k-1
è troppo difficile da raggiungere (i dati che abbiamo incontrato non sono per lo più numeri, quasi mai distribuiti uniformemente e possono essere tra qualsiasi valore. Ma usando una buona funzione di hashing puoi supporre che i bit di output sarebbero distribuiti uniformemente e la maggior parte della funzione di hashing ha output tra 0
e 2^k - 1
( SHA1 fornisce valori tra 0
e la carta di conteggio probabilistica del 1984 (è un po 'più intelligente con la stima, ma siamo ancora vicini).2^160
). Ciò che abbiamo ottenuto finora è che possiamo stimare il numero di elementi unici con la massima cardinalità dei k
bit memorizzando solo un numero di log(k)
bit di dimensioni . Il rovescio della medaglia è che abbiamo una grande varianza nella nostra stima. Una cosa interessante che abbiamo quasi creato
loglog
Prima di andare oltre, dobbiamo capire perché la nostra prima stima non è eccezionale. Il motivo è che una ricorrenza casuale di elemento 0-prefisso ad alta frequenza può rovinare tutto. Un modo per migliorarlo è usare molte funzioni di hash, contare il massimo per ciascuna delle funzioni di hash e alla fine farne una media. Questa è un'idea eccellente, che migliorerà la stima, ma la carta LogLog ha usato un approccio leggermente diverso (probabilmente perché l'hashing è un po 'costoso).
Hanno usato un hash ma lo hanno diviso in due parti. Uno si chiama bucket (il numero totale di bucket è 2^x
) e un altro - è sostanzialmente lo stesso del nostro hash. È stato difficile per me ottenere quello che stava succedendo, quindi farò un esempio. Supponi di avere due elementi e la tua funzione hash che dia forma 0
ai 2^10
valori prodotti 2: 344
e 387
. Hai deciso di avere 16 secchi. Quindi hai:
0101 011000 bucket 5 will store 1
0110 000011 bucket 6 will store 4
Avendo più secchi si riduce la varianza (si utilizza leggermente più spazio, ma è ancora minuscolo). Usando le abilità matematiche sono stati in grado di quantificare l'errore (che è 1.3/sqrt(number of buckets)
).
HyperLogLog
HyperLogLog non introduce nuove idee, ma utilizza principalmente molta matematica per migliorare la stima precedente. I ricercatori hanno scoperto che se si rimuove il 30% dei numeri più grandi dai bucket, si migliora significativamente la stima. Hanno anche usato un altro algoritmo per la media dei numeri. Il documento è pesante per la matematica.
E voglio finire con un recente documento, che mostra una versione migliorata dell'algoritmo hyperLogLog (fino ad ora non ho avuto il tempo di comprenderlo appieno, ma forse in seguito migliorerò questa risposta).