Algoritmi di streaming - campionamento di riserva e conteggio degli elementi distinti
In questa pagina 5
Definizione (modello a flusso). Gli elementi arrivano uno alla volta, si leggono una volta sola e non si possono riguardare. La memoria è molto minore di (spesso polilogaritmica) e può essere ignoto. Gli algoritmi sono randomizzati e approssimati: si chiede una stima entro con probabilità almeno .
È il caso dei contatori di un router, dei log di un server, dei dati dei sensori. Gli strumenti sono quelli già visti: valore atteso e varianza (Linearità del valore atteso e variabili indicatriciLa linearità $E[X+Y]=E[X]+E[Y]$ vale sempre, anche senza indipendenza; con le variabili indicatrici ($E[I_A]=P(A)$) trasforma un conteggio in una somma di probabilità. Applicazioni: attesa del primo successo $1/p$, collezionista di figurine $nH_n$, punti fissi di una permutazione (media $1$), record (media $H_n$), inversioni ($n(n-1)/4$), attesa condizionata, identità di Wald $E[S_N]=E[N]E[X]$.Linearità del valore atteso e variabili indicatrici →, Momenti e deviazioni - Markov, Chebyshev e mediana randomizzataVar(ΣX_i) = ΣVar + 2ΣCov, e basta l'indipendenza a coppie perché la varianza si sommi. Chebyshev dà code polinomiali (collezionista: P(T ≥ nH_n + cn) ≤ π²/(6c²)); il metodo del secondo momento dà P(X=0) ≤ Var(X)/E[X]². Algoritmo della mediana: campione di n^(3/4) elementi, due estremi d e u a ±√n, ordinamento dei soli elementi tra d e u; fallisce con probabilità ≤ n^(-1/4) ed è Las Vegas con 2n + o(n) confronti.Momenti e deviazioni - Markov, Chebyshev e mediana randomizzata →), l'hashing universale (Hashing randomizzato - famiglie universali, filtri di Bloom e fingerprintHashing con catene e costo atteso 1+alfa; famiglie universali (probabilità di collisione al più 1/m) e costruzione h(x)=((ax+b) mod p) mod m con dimostrazione; hashing perfetto a due livelli (spazio lineare, ricerca O(1) nel caso peggiore); filtri di Bloom: falsi positivi (1-e^(-kn/m))^k e k ottimo (m/n) ln 2; fingerprint di stringhe e numero di bit necessari.Hashing randomizzato - famiglie universali, filtri di Bloom e fingerprint →) e l'amplificazione per ripetizione (Algoritmi randomizzati - Monte Carlo, Las Vegas e amplificazioneUn algoritmo randomizzato usa bit casuali indipendenti; la probabilità è sulle scelte dell'algoritmo, mai sull'input (garanzia per ogni input). Las Vegas: sempre corretto, tempo aleatorio (conta il tempo atteso). Monte Carlo: tempo fisso, risposta sbagliata con probabilità limitata; errore unilaterale (RP: accetta solo se x sta nel linguaggio, accetta con prob almeno 1/2) o bilaterale (BPP: giusto con prob almeno 2/3). ZPP = RP ∩ co-RP = Las Vegas con tempo atteso polinomiale. Amplificazione: unilaterale, k ripetizioni indipendenti, errore (1-p)^k ≤ e^(-pk), serve k ≥ ln(1/ε)/p; bilaterale, voto di maggioranza su k esecuzioni, errore binomiale esatto, esponenziale in k (Chernoff, e^(-k/18) per p=2/3) mentre Chebyshev dà solo 8/k. Las Vegas -> Monte Carlo: interrompere a c volte il tempo atteso (Markov, errore ≤ 1/c). Monte Carlo -> Las Vegas: solo se la risposta si verifica in fretta. Esempio: Miller-Rabin, errore ≤ 1/4 per esecuzione.Algoritmi randomizzati - Monte Carlo, Las Vegas e amplificazione →).
Campionamento di riserva
Problema. Estrarre dal flusso un campione di elementi, uniforme tra i sottoinsiemi possibili, con memoria e senza conoscere .
Algoritmo (reservoir sampling). Si tengono i primi elementi. All'arrivo dell'elemento : si estrae uniforme in ; se l'elemento sostituisce quello nello slot , altrimenti viene scartato.
Teorema. Dopo aver letto elementi, ognuno di essi è nel campione con probabilità esattamente (e ogni sottoinsieme di elementi ha probabilità ).
Dimostrazione (per induzione su ). Per la probabilità è . Passo : l'elemento nuovo entra con probabilità . Un elemento vecchio è nel campione con probabilità (ipotesi induttiva); dato che lo è, occupa uno slot e viene espulso solo se coincide con quello slot, cioè con probabilità ; quindi sopravvive con probabilità e la probabilità totale è . Per : l'elemento sostituisce con probabilità e poi non viene più sostituito con probabilità , in totale .
Esempio (, , elenco esatto). Si enumerano tutte le scelte casuali del programma (con probabilità razionali): ognuno dei elementi è nel campione con probabilità e ognuno dei sottoinsiemi ha probabilità . L'algoritmo "ogni nuovo elemento entra con probabilità in uno slot a caso" non è uniforme: con , dà ai primi due elementi e all'ultimo, invece di a tutti. Per e sostituzione con probabilità i cinque elementi hanno probabilità .
Contatore di Morris
Problema. Contare fino a con bit invece di , accettando un'approssimazione.
Algoritmo (contatore di Morris). Si memorizza solo un piccolo intero , inizialmente . A ogni evento: con probabilità si pone . Stima: .
Idea: approssima , e per incrementarlo da a servono in media eventi, ciascuno dei quali pesa quanto la stima.
Teorema. Dopo eventi, (stima non distorta) e .
Dimostrazione. Sia . Dato : con probabilità e altrimenti. Quindi Prendendo i valori attesi: e . Con la prima dà . Sostituendo nella seconda, . Infine .
Esempio (). vale con probabilità (da : sale con ; da : sale con ). Le stime danno , come deve. L'enumerazione esatta con frazioni conferma e per .
Precisione. La deviazione standard è grande quanto la stima: un solo contatore è troppo grossolano. Rimedi:
- Media di contatori indipendenti: varianza ; per Chebyshev , e basta per probabilità di errore (per : ).
- Base : si incrementa con probabilità e si stima ; la stima resta non distorta e (verificato esattamente per e , : e ). Con un solo contatore dà per Chebyshev. Con () e , : bit invece dei del conteggio esatto.
Simulazione (, ). Su prove la media delle stime è e la deviazione standard (teoria ); vale in media () e al massimo . La media di contatori ha deviazione standard (teoria ), e in prove nessuna volta l'errore supera il di .
Elementi distinti
Problema. Quanti valori diversi compaiono nel flusso? Con memoria è banale (insieme dei visti); si vuole una stima con memoria piccola.
Idea comune. Una funzione hash casuale manda ogni valore distinto in un punto uniforme di , e i duplicati nello stesso punto: la statistica che si guarda dipende solo dall'insieme dei distinti.
Flajolet-Martin (idea)
Si mandano gli elementi in stringhe di bit e si indica con il numero di zeri finali dell'hash: . Con valori distinti, circa hanno : l'indice massimo è vicino a e è una stima grossolana di (dopo una costante di correzione ). Una sola copia è però molto variabile. In prove con () il valore va da a (mediano ): per ottenere una buona stima si usano molte copie e la mediana.
Il -esimo minimo
Algoritmo (-esimo minimo, bottom-). Con che manda i valori in si tengono i valori hash distinti più piccoli visti. Se è il -esimo più piccolo la stima è Se i distinti sono meno di si conta direttamente.
Perché funziona. Con punti uniformi indipendenti, il minimo vale in media : , quindi (per la simulazione dà contro ). Più punti ci sono, più i minimi sono piccoli: . Con la stima è però inutilizzabile: diverge vicino a , quindi media e varianza sono infinite. Per , da , il e il delle stime valgono e .
Teorema. Per , (stima non distorta) e lo scarto relativo è circa .
Dimostrazione della media. La densità del -esimo più piccolo di punti uniformi è (si sceglie quali punti stanno sotto, quale è , e gli altri stanno sopra). Quindi dove l'integrale è la funzione Beta. La varianza si calcola allo stesso modo e dà . Per Chebyshev, con la stima è entro con probabilità , amplificabile con la mediana di copie indipendenti. La memoria è valori hash, indipendente da e da .
Simulazione (, flusso con ripetizioni). Con su prove: media , scarto relativo (teoria ), delle stime entro il . Con : media , scarto (teoria ), entro il .
Count-Min sketch
Problema. Stimare la frequenza di ogni elemento (numero di arrivi) con memoria piccola, per esempio per trovare gli elementi più frequenti.
Definizione (Count-Min sketch). Una matrice di righe e colonne di contatori, inizialmente , e funzioni hash indipendenti da una famiglia universale. Arrivo di : per ogni riga . Stima: .
Teorema (garanzia ). Sia il numero totale di arrivi. Con e :
Dimostrazione. Nella riga la cella di contiene più l'errore , quindi . Per l'universalità e, per la linearità, . Markov (in modo valido perché ): . Le righe sono indipendenti, e richiede che tutte le righe superino : probabilità .
Esempio piccolo (, , ). Funzioni con ; flusso di arrivi con frequenze , , , , , . Posizioni (riga //): , , , , , . Contatori finali:
| riga | colonna | ||||
|---|---|---|---|---|---|
La colonna della riga vale (collidono ), la colonna della riga vale ( e ), la colonna della riga vale . Stime: (vero : sovrastima di , perché collide con nelle righe e e con e nella riga ), tutte le altre sono esatte; l'elemento mai visto va nelle colonne (, , modulo , poi modulo ), con contatori , e ha stima . Nessuna stima è sotto la frequenza vera.
Dimensionamento. Per e : colonne e righe, cioè contatori indipendentemente dal numero di elementi distinti. L'errore additivo è : va bene per gli elementi frequenti (), non per quelli rari.
Simulazione. Su un flusso di arrivi su valori con distribuzione di tipo Zipf, con , (, ) l'errore massimo osservato su tutti i valori è ; con , (, ) è .
import random, heapq, hashlib
from math import e, log, ceil
def riserva(flusso, k):
"""Campione uniforme di k elementi da un flusso di lunghezza ignota."""
r = []
for i, x in enumerate(flusso, 1):
if i <= k:
r.append(x)
elif (j := random.randrange(1, i + 1)) <= k: # entra con probabilità k/i
r[j - 1] = x # al posto di uno slot a caso
return r
def morris(n):
X = 0
for _ in range(n):
if random.random() < 2.0 ** -X: # incrementa con probabilità 2^-X
X += 1
return 2 ** X - 1 # stima non distorta di n
def h01(x): # hash in (0,1)
d = hashlib.blake2b(str(x).encode(), digest_size=8).digest()
return (int.from_bytes(d, "big") + 0.5) / 2 ** 64
def distinti(flusso, k):
"""k-esimo minimo: stima (k-1)/v_k del numero di elementi distinti."""
heap, visti = [], set() # max-heap (valori negati) dei k minimi
for x in flusso:
v = h01(x)
if v in visti:
continue
if len(heap) < k:
heapq.heappush(heap, -v); visti.add(v)
elif v < -heap[0]:
visti.discard(-heapq.heappushpop(heap, -v)); visti.add(v)
return len(heap) if len(heap) < k else (k - 1) / -heap[0]
class CountMin:
P = (1 << 61) - 1
def __init__(self, eps, delta):
self.w, self.d = ceil(e / eps), ceil(log(1 / delta))
self.ab = [(random.randrange(1, self.P), random.randrange(self.P)) for _ in range(self.d)]
self.C = [[0] * self.w for _ in range(self.d)]
def _col(self, j, x):
a, b = self.ab[j]
return ((a * x + b) % self.P) % self.w
def aggiungi(self, x, c=1):
for j in range(self.d):
self.C[j][self._col(j, x)] += c
def stima(self, x): # mai sotto la frequenza vera
return min(self.C[j][self._col(j, x)] for j in range(self.d))Con arrivi su valori casuali ( distinti) il programma completo stima elementi distinti con , e un valore comparso volte ha stima in un Count-Min con (errore : per gli elementi rari la garanzia additiva è debole).
Domande d'esame
- Dimostra che il reservoir sampling con restituisce un elemento uniforme. L'elemento entra con probabilità e sopravvive ai passi con probabilità ; prodotto .
- Dimostra che il contatore di Morris è non distorto. , quindi e .
- Con quanti contatori di Morris si ottiene errore relativo con probabilità ? Chebyshev: , quindi .
- Perché nello sketch Count-Min si prende il minimo e non la media delle righe? Ogni cella contiene la frequenza vera più un errore da collisioni: il minimo è la cella meno contaminata e non è mai sotto ; la media includerebbe anche le righe peggiori.
Versione ripasso
- Modello. Elementi letti una sola volta, memoria , ignoto; stima entro con probabilità (Momenti e deviazioni - Markov, Chebyshev e mediana randomizzataVar(ΣX_i) = ΣVar + 2ΣCov, e basta l'indipendenza a coppie perché la varianza si sommi. Chebyshev dà code polinomiali (collezionista: P(T ≥ nH_n + cn) ≤ π²/(6c²)); il metodo del secondo momento dà P(X=0) ≤ Var(X)/E[X]². Algoritmo della mediana: campione di n^(3/4) elementi, due estremi d e u a ±√n, ordinamento dei soli elementi tra d e u; fallisce con probabilità ≤ n^(-1/4) ed è Las Vegas con 2n + o(n) confronti.Momenti e deviazioni - Markov, Chebyshev e mediana randomizzata →, Linearità del valore atteso e variabili indicatriciLa linearità $E[X+Y]=E[X]+E[Y]$ vale sempre, anche senza indipendenza; con le variabili indicatrici ($E[I_A]=P(A)$) trasforma un conteggio in una somma di probabilità. Applicazioni: attesa del primo successo $1/p$, collezionista di figurine $nH_n$, punti fissi di una permutazione (media $1$), record (media $H_n$), inversioni ($n(n-1)/4$), attesa condizionata, identità di Wald $E[S_N]=E[N]E[X]$.Linearità del valore atteso e variabili indicatrici →). L'amplificazione si fa con la media o con la mediana di copie indipendenti (Algoritmi randomizzati - Monte Carlo, Las Vegas e amplificazioneUn algoritmo randomizzato usa bit casuali indipendenti; la probabilità è sulle scelte dell'algoritmo, mai sull'input (garanzia per ogni input). Las Vegas: sempre corretto, tempo aleatorio (conta il tempo atteso). Monte Carlo: tempo fisso, risposta sbagliata con probabilità limitata; errore unilaterale (RP: accetta solo se x sta nel linguaggio, accetta con prob almeno 1/2) o bilaterale (BPP: giusto con prob almeno 2/3). ZPP = RP ∩ co-RP = Las Vegas con tempo atteso polinomiale. Amplificazione: unilaterale, k ripetizioni indipendenti, errore (1-p)^k ≤ e^(-pk), serve k ≥ ln(1/ε)/p; bilaterale, voto di maggioranza su k esecuzioni, errore binomiale esatto, esponenziale in k (Chernoff, e^(-k/18) per p=2/3) mentre Chebyshev dà solo 8/k. Las Vegas -> Monte Carlo: interrompere a c volte il tempo atteso (Markov, errore ≤ 1/c). Monte Carlo -> Las Vegas: solo se la risposta si verifica in fretta. Esempio: Miller-Rabin, errore ≤ 1/4 per esecuzione.Algoritmi randomizzati - Monte Carlo, Las Vegas e amplificazione →).
- Reservoir sampling. Si tengono i primi ; l'elemento ha uniforme e, se , sostituisce lo slot . Dopo elementi ognuno è nel campione con probabilità (e ogni sottoinsieme di ha probabilità ). Induzione: il nuovo entra con ; un vecchio, nel campione con , viene espulso solo se è il suo slot, probabilità , quindi resta con . Per : . Esempio , (enumerazione esatta con frazioni): ogni elemento , ogni coppia ; l'alternativa "entra con " non è uniforme ( ai primi due, all'ultimo).
- Morris. con probabilità , stima ; bit. Con : e ; quindi (non distorta), , , sd (simulato per ). Esempio : con , stime , media . Media di contatori: Chebyshev , quindi ( per ). Base : , con un solo contatore basta ( bit per invece di ).
- Distinti. Hash in che manda i duplicati nello stesso punto. Flajolet-Martin: = zeri finali, , ma una copia sola è molto variabile (: da a ): mediana di molte copie. -esimo minimo: . . Il -esimo ha densità , quindi (funzione Beta); sd relativo ( per , simulato ; per ); memoria . Con media e varianza della stima sono infinite.
- Count-Min. Matrice , , . Errore di riga con (universalità + linearità); con Markov dà ; righe indipendenti: . , : contatori. Esempio , , : contro , le altre esatte, l'elemento assente ha stima . L'errore additivo è debole sui rari (Hashing randomizzato - famiglie universali, filtri di Bloom e fingerprintHashing con catene e costo atteso 1+alfa; famiglie universali (probabilità di collisione al più 1/m) e costruzione h(x)=((ax+b) mod p) mod m con dimostrazione; hashing perfetto a due livelli (spazio lineare, ricerca O(1) nel caso peggiore); filtri di Bloom: falsi positivi (1-e^(-kn/m))^k e k ottimo (m/n) ln 2; fingerprint di stringhe e numero di bit necessari.Hashing randomizzato - famiglie universali, filtri di Bloom e fingerprint →).
- Errori tipici. Prendere la media anziché il minimo nel Count-Min; confondere con ; stimare i distinti con ; dimenticare che un solo contatore di Morris ha errore relativo costante; non contare i duplicati una sola volta nell'insieme dei minimi.