Algoritmi "on-line" (iteratori) per la stima di mediana statistica, modo, asimmetria, curtosi?


86

Esiste un algoritmo per stimare la mediana, la modalità, l'asimmetria e / o la curtosi di un insieme di valori, ma questo NON richiede la memorizzazione di tutti i valori contemporaneamente?

Vorrei calcolare le statistiche di base:

  • media: media aritmetica
  • varianza: media delle deviazioni quadrate dalla media
  • deviazione standard: radice quadrata della varianza
  • mediana: valore che separa la metà più grande dei numeri dalla metà più piccola
  • mode: valore più frequente trovato nel set
  • asimmetria: tl; dr
  • curtosi: tl; dr

La formula di base per calcolare uno di questi è l'aritmetica della scuola elementare, e io le conosco. Ci sono anche molte librerie di statistiche che le implementano.

Il mio problema è il gran numero (miliardi) di valori nei set che sto gestendo: lavorando in Python, non posso semplicemente creare un elenco o un hash con miliardi di elementi. Anche se ho scritto questo in C, gli array di miliardi di elementi non sono troppo pratici.

I dati non vengono ordinati. Viene prodotto in modo casuale, al volo, da altri processi. La dimensione di ogni set è molto variabile e le dimensioni non saranno note in anticipo.

Ho già capito come gestire la media e la varianza abbastanza bene, ripetendo ogni valore nell'insieme in qualsiasi ordine. (In realtà, nel mio caso, li prendo nell'ordine in cui sono generati.) Ecco l'algoritmo che sto usando, per gentile concessione di http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm :

  • Inizializza tre variabili: count, sum e sum_of_squares
  • Per ogni valore:
    • Conteggio incremento.
    • Aggiungi il valore alla somma.
    • Aggiungi il quadrato del valore a sum_of_squares.
  • Dividi la somma per conteggio, memorizzando come media della variabile.
  • Dividi sum_of_squares per count, memorizzando come variabile mean_of_squares.
  • Media quadrata, memorizzazione come square_of_mean.
  • Sottrai square_of_mean da mean_of_squares, memorizzando come varianza.
  • Media e varianza di output.

Questo algoritmo "in linea" ha dei punti deboli (ad esempio, problemi di precisione poiché sum_of_squares cresce rapidamente più grande dell'intervallo intero o della precisione del float), ma fondamentalmente mi dà ciò di cui ho bisogno, senza dover memorizzare ogni valore in ogni set.

Ma non so se esistano tecniche simili per stimare le statistiche aggiuntive (mediana, modo, asimmetria, curtosi). Potrei convivere con uno stimatore parziale, o anche un metodo che compromette l'accuratezza in una certa misura, purché la memoria richiesta per elaborare N valori sia sostanzialmente inferiore a O (N).

Anche indicarmi una libreria di statistiche esistente sarà d'aiuto, se la libreria ha funzioni per calcolare una o più di queste operazioni "on-line".


i dati verranno passati in ordine e saprai in anticipo il numero di input?
chillysapien

Utile collegamento esistente su StackOverflow: stackoverflow.com/questions/895929/...
dmckee --- ex-moderatore gattino

Sono dati interi o dati float? Hai un valore massimo o minimo?
stephan

dmckee: In realtà sto usando il metodo di Welford per la deviazione standard. Ma non vedo nulla in quel collegamento su modalità, mediana, curtosi o asimmetria ... Mi manca qualcosa?
Ryan B. Lynch,

stephan: Alcuni set di dati sono numeri interi, altri sono float. La distribuzione della popolazione è abbastanza vicina al normale (gaussiano), quindi possiamo stabilire un intervallo di confidenza, ma non esiste un limite di intervallo rigido (tranne x> 0, in alcuni casi).
Ryan B. Lynch,

Risposte:


53

Asimmetria e curtosi

Per gli algoritmi in linea per Skewness e Kurtosis (sulla falsariga della varianza), vedere nella stessa pagina wiki qui gli algoritmi paralleli per le statistiche dei momenti più alti.

Mediano

La mediana è difficile senza dati ordinati. Se sai quanti punti dati hai, in teoria devi solo ordinare parzialmente, ad esempio utilizzando un algoritmo di selezione . Tuttavia, ciò non aiuta molto con miliardi di valori. Suggerirei di utilizzare i conteggi di frequenza, vedere la sezione successiva.

Mediana e modalità con conteggi di frequenza

Se sono numeri interi, conterei le frequenze , probabilmente tagliando i valori più alto e più basso oltre un valore in cui sono sicuro che non sia più rilevante. Per i float (o troppi numeri interi), creerei probabilmente bucket / intervalli e quindi utilizzerei lo stesso approccio degli interi. Modalità (approssimativa) e calcolo della mediana più facili, in base alla tabella delle frequenze.

Variabili casuali normalmente distribuite

Se è normalmente distribuito, userei popolazione campione medio , varianza , asimmetria e curtosi come stimatori massima verosimiglianza per un piccolo sottoinsieme. Gli algoritmi (in linea) per calcolarli, già adesso. Ad esempio, leggi un paio di centinaia di migliaia o milioni di punti dati, finché l'errore di stima non diventa abbastanza piccolo. Assicurati solo di scegliere a caso dal tuo set (ad esempio, di non introdurre un bias scegliendo i primi 100'000 valori). Lo stesso approccio può essere utilizzato anche per la stima della modalità e della mediana per il caso normale (per entrambi la media campionaria è uno stimatore).

Ulteriori commenti

Tutti gli algoritmi di cui sopra possono essere eseguiti in parallelo (inclusi molti algoritmi di ordinamento e selezione, ad esempio QuickSort e QuickSelect), se questo aiuta.

Ho sempre ipotizzato (con l'eccezione della sezione sulla distribuzione normale) che si parli di momenti campionari, mediana e modo, non stimatori per momenti teorici data una distribuzione nota.

In generale, il campionamento dei dati (cioè solo guardando un sottoinsieme) dovrebbe avere un discreto successo data la quantità di dati, purché tutte le osservazioni siano realizzazioni della stessa variabile casuale (abbiano le stesse distribuzioni) e i momenti, la modalità e la mediana esiste effettivamente per questa distribuzione. L'ultimo avvertimento non è innocuo. Ad esempio, la media (e tutti i momenti superiori) per la distribuzione di Cauchy non esistono. In questo caso, la media campionaria di un sottoinsieme "piccolo" potrebbe essere notevolmente discostata dalla media campionaria dell'intero campione.


57

Uso questi stimatori incrementali / ricorsivi media e mediana, che utilizzano entrambi la memorizzazione costante:

mean += eta * (sample - mean)
median += eta * sgn(sample - median)

dove eta è un piccolo parametro della velocità di apprendimento (es. 0.001) e sgn () è la funzione signum che restituisce uno di {-1, 0, 1}. (Usa una costante eta se i dati non sono stazionari e vuoi tenere traccia dei cambiamenti nel tempo; altrimenti, per sorgenti stazionarie puoi usare qualcosa come eta = 1 / n per lo stimatore medio, dove n è il numero di campioni visti così lontano ... sfortunatamente, questo non sembra funzionare per lo stimatore mediano.)

Questo tipo di stimatore medio incrementale sembra essere utilizzato ovunque, ad esempio nelle regole di apprendimento della rete neurale senza supervisione, ma la versione mediana sembra molto meno comune, nonostante i suoi benefici (robustezza ai valori anomali). Sembra che la versione mediana possa essere utilizzata in sostituzione dello stimatore medio in molte applicazioni.

Mi piacerebbe vedere uno stimatore in modalità incrementale di una forma simile ...

AGGIORNARE

Ho appena modificato lo stimatore mediano incrementale per stimare quantili arbitrari. In generale, una funzione quantile ( http://en.wikipedia.org/wiki/Quantile_function ) ti dice il valore che divide i dati in due frazioni: pe 1-p. Quanto segue stima questo valore in modo incrementale:

quantile += eta * (sgn(sample - quantile) + 2.0 * p - 1.0)

Il valore p dovrebbe essere entro [0,1]. Questo essenzialmente sposta l' output simmetrico della funzione sgn () {-1,0,1} in modo che si inclini verso un lato, partizionando i campioni di dati in due contenitori di dimensioni non uguali (le frazioni pe 1-p dei dati sono minori / maggiori di la stima quantile, rispettivamente). Si noti che per p = 0,5, questo si riduce allo stimatore mediano.


3
Questo stimatore mediano è ottimo. Sai se esistono stimatori simili per quantili 0,25 / 0,75?
Gacek

1
@ Gacek, certo: dividi il flusso di input in Lohalf <median and Hihalf> median, e usa running-median su ciascuna metà.
denis

2
@ Gacek: ho appena aggiornato la mia risposta con un metodo incrementale per stimare qualsiasi quantile, in cui puoi impostare p su 0,25, 0,75 o qualsiasi valore compreso tra [0,1].
Tyler Streeter

10
Funziona alla grande per la media, ma non vedo come produca qualcosa di lontanamente vicino alla mediana. Prendi una sequenza di timestamp in millisec, ad esempio: [1328083200000, 981014400000, -628444800000, 318240000000, 949392000000]che hanno una mediana di 318240000000. Questa equazione sposta la mediana precedente di +/- etadi cui era il valore consigliato 0.001. Non farà nulla per grandi numeri come questi, e potrebbe essere troppo grande per numeri veramente piccoli. Come sceglieresti uno etache ti abbia dato la risposta giusta senza conoscere la risposta a priori?
mckamey

9
Immagina che i numeri abbiano unità, ad esempio, millimetri. Quindi è chiaro che eta (per la stima della mediana) deve avere le stesse unità delle misurazioni, quindi un valore generico come 0,001 semplicemente non ha alcun senso. Un approccio apparentemente migliore consiste nell'impostare eta da una stima corrente della deviazione assoluta: per ogni nuovo valore sample, aggiorna cumadev += abs(sample-median). Quindi impostare eta = 1.5*cumadev/(k*k), dov'è kil numero di campioni visti finora.
tholy

12

Ho implementato l' algoritmo P-Square per il calcolo dinamico di quantili e istogrammi senza memorizzare osservazioni in un modulo Python pulito che ho scritto chiamato LiveStats . Dovrebbe risolvere il tuo problema in modo abbastanza efficace. La libreria supporta tutte le statistiche menzionate ad eccezione della modalità. Non ho ancora trovato una soluzione soddisfacente per la stima della modalità.


FYI: l'algoritmo di p-piazza è in C ++ spinta: <boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp>.
Neil G

7

Ryan, temo che tu non stia facendo bene la media e la varianza ... Questo è emerso alcune settimane fa qui . E uno dei punti di forza della versione online (che in realtà prende il nome di metodo di Welford) è il fatto che è particolarmente accurato e stabile, vedi la discussione qui . Uno dei punti di forza è il fatto che non è necessario memorizzare la somma totale o la somma totale dei quadrati ...

Non riesco a pensare a nessun approccio in linea alla modalità e alla mediana, che sembra richiedere di considerare l'intero elenco in una volta. Ma può benissimo essere che un approccio simile a quello per la varianza e la media funzionerà anche per l'asimmetria e la curtosi ...


ri: skewness and kurtosisSì. Vedi questo articolo: johndcook.com/blog/skewness_kurtosis
Jesse Chisholm

3

L'articolo di Wikipedia citato nella domanda contiene le formule per il calcolo dell'asimmetria e della curtosi in linea.

Per la modalità - credo - non c'è modo di farlo online. Perché? Supponiamo che tutti i valori del tuo input siano diversi dall'ultimo che duplica uno precedente. In questo caso bisogna ricordare tutti i valori già visti nell'ingresso per rilevare che l'ultimo valore duplica un valore visto prima e lo rende il più frequente.

Per la mediana è quasi lo stesso: fino all'ultimo input non sai quale valore diventerà la mediana se tutti i valori di input sono diversi perché potrebbe essere prima o dopo la mediana corrente. Se conosci la lunghezza dell'input, puoi trovare la mediana senza memorizzare tutti i valori in memoria, ma dovrai comunque memorizzarne molti (immagino intorno alla metà) perché una cattiva sequenza di input potrebbe spostare pesantemente la mediana nel secondo tempo eventualmente valorizzando dal primo tempo la mediana.

(Nota che mi riferisco solo al calcolo esatto.)


2

Se hai miliardi di punti dati, è improbabile che tu abbia bisogno di risposte esatte, invece di risposte chiuse. In generale, se si hanno miliardi di punti dati, il processo sottostante che li genera probabilmente obbedirà a qualche tipo di proprietà statistica di stazionarietà / ergodicità / miscelazione. Inoltre può essere importante se ti aspetti che le distribuzioni siano ragionevolmente continue o meno.

In queste circostanze, esistono algoritmi per la stima dei quantili in linea, con poca memoria (la mediana è un caso speciale di 0,5 quantile), così come i modi, se non hai bisogno di risposte esatte. Questo è un campo statistico attivo.

esempio di stima quantile: http://www.computer.org/portal/web/csdl/doi/10.1109/WSC.2006.323014

esempio di stima della modalità: Bickel DR. Stimatori affidabili della modalità e dell'asimmetria dei dati continui. Statistica computazionale e analisi dei dati. 2002; 39: 153–163. doi: 10.1016 / S0167-9473 (01) 00057-3.

Questi sono campi attivi della statistica computazionale. Stai entrando in campi in cui non esiste un singolo algoritmo esatto, ma una varietà di essi (stimatori statistici, in verità), che hanno proprietà, ipotesi e prestazioni diverse. È matematica sperimentale. Probabilmente ci sono centinaia o migliaia di articoli sull'argomento.

L'ultima domanda è se hai davvero bisogno di asimmetria e curtosi da sole, o più probabilmente di altri parametri che possono essere più affidabili nel caratterizzare la distribuzione di probabilità (supponendo che tu abbia una distribuzione di probabilità!). Ti aspetti una gaussiana?

Avete modi per pulire / preelaborare i dati per renderli prevalentemente gaussiani? (per esempio, gli importi delle transazioni finanziarie sono spesso un po 'gaussiani dopo aver preso i logaritmi). Ti aspetti deviazioni standard finite? Ti aspetti code grasse? Le quantità che ti interessano sono nelle code o alla rinfusa?


2

Tutti continuano a dire che non puoi fare la modalità in modo online, ma semplicemente non è vero. Ecco un articolo che descrive un algoritmo per fare proprio questo problema inventato nel 1982 da Michael E. Fischer e Steven L. Salzberg dell'Università di Yale. Dall'articolo:

L'algoritmo di ricerca della maggioranza utilizza uno dei suoi registri per l'archiviazione temporanea di un singolo elemento dal flusso; questo elemento è l'attuale candidato per l'elemento di maggioranza. Il secondo registro è un contatore inizializzato a 0. Per ogni elemento del flusso, chiediamo all'algoritmo di eseguire la seguente routine. Se il contatore legge 0, installa l'elemento stream corrente come nuovo candidato di maggioranza (rimpiazzando qualsiasi altro elemento che potrebbe essere già nel registro). Quindi, se l'elemento corrente corrisponde al candidato di maggioranza, incrementa il contatore; in caso contrario, diminuire il contatore. A questo punto del ciclo, se la parte del flusso visto finora ha un elemento di maggioranza, quell'elemento è nel registro candidato e il contatore ha un valore maggiore di 0. E se non ci fosse un elemento di maggioranza? Senza fare un secondo passaggio attraverso i dati, cosa che non è possibile in un ambiente di flusso, l'algoritmo non può sempre dare una risposta univoca in questa circostanza. Promette semplicemente di identificare correttamente l'elemento di maggioranza se ce n'è uno.

Può anche essere esteso per trovare il primo N con più memoria, ma questo dovrebbe risolverlo per la modalità.


4
Questo è un algoritmo interessante, ma a meno che non mi manchi qualcosa, mentre tutti i valori di maggioranza saranno modalità, non tutte le modalità saranno valori di maggioranza.
jkebinger

Il collegamento è morto, quindi sono contento che la descrizione sia inclusa. MA, come descritto, il contatore aumenta solo se la seconda occorrenza del candidato maggioritario è adiacente alla prima occorrenza. Quale IMPLICA i dati ordinati. Che NON è garantito nel caso dei dati online (streaming). Con dati ordinati in modo casuale, è improbabile che sia possibile trovare modalità.
Jesse Chisholm

1

In definitiva, se non si ha una conoscenza parametrica a priori della distribuzione, penso che sia necessario memorizzare tutti i valori.

Detto questo, a meno che tu non abbia a che fare con una sorta di situazione patologica, il rimedio (Rousseuw e Bassett 1990) potrebbe essere abbastanza buono per i tuoi scopi.

Molto semplicemente comporta il calcolo della mediana dei lotti di mediane.


0

mediana e modalità non possono essere calcolate online utilizzando solo lo spazio disponibile costante. Tuttavia, poiché mediana e modo sono comunque più "descrittivi" che "quantitativi", è possibile stimarli ad esempio campionando il set di dati.

Se i dati sono distribuiti normalmente nel lungo periodo, potresti semplicemente usare la tua media per stimare la mediana.

Puoi anche stimare la mediana utilizzando la seguente tecnica: stabilire una stima mediana M [i] per ogni, diciamo, 1.000.000 di voci nel flusso di dati in modo che M [0] sia la mediana del primo milione di voci, M [1] il mediana del secondo milione di voci ecc. Quindi utilizzare la mediana di M [0] ... M [k] come stimatore mediano. Questo ovviamente consente di risparmiare spazio e puoi controllare quanto vuoi utilizzare lo spazio "sintonizzando" il parametro 1.000.000. Questo può anche essere generalizzato ricorsivamente.


0

OK amico, prova questi:

per c ++:

double skew(double* v, unsigned long n){
    double sigma = pow(svar(v, n), 0.5);
    double mu = avg(v, n);

    double* t;
    t = new double[n];

    for(unsigned long i = 0; i < n; ++i){
        t[i] = pow((v[i] - mu)/sigma, 3);
    }

    double ret = avg(t, n);

    delete [] t;
    return ret;
}

double kurt(double* v, double n){
    double sigma = pow(svar(v, n), 0.5);
    double mu = avg(v, n);

    double* t;
    t = new double[n];

    for(unsigned long i = 0; i < n; ++i){
        t[i] = pow( ((v[i] - mu[i]) / sigma) , 4) - 3;
    }

    double ret = avg(t, n);

    delete [] t;
    return ret;
}

dove dici che puoi già calcolare la varianza del campione (svar) e la media (avg), indirizzali alle tue funzioni per farlo.

Inoltre, dai un'occhiata alla cosa dell'approssimazione di Pearson. su un set di dati così ampio sarebbe abbastanza simile. 3 (media - mediana) / deviazione standard hai mediana come max - min / 2

per la modalità float non ha significato. normalmente si inseriscono in contenitori di dimensioni importanti (come 1/100 * (max - min)).



-1

Tenderei a usare i bucket, che potrebbero essere adattivi. La dimensione del secchio dovrebbe corrispondere alla precisione di cui hai bisogno. Quindi, quando ogni punto dati arriva, ne aggiungi uno al conteggio del bucket pertinente. Questi dovrebbero darti semplici approssimazioni alla mediana e alla curtosi, contando ogni bucket come il suo valore ponderato per il suo conteggio.

L'unico problema potrebbe essere la perdita di risoluzione in virgola mobile dopo miliardi di operazioni, cioè aggiungerne una non cambia più il valore! Per ovviare a questo problema, se la dimensione massima del bucket supera un certo limite, potresti togliere un numero elevato da tutti i conteggi.


-1
for j in range (1,M):
    y=np.zeros(M) # build the vector y
    y[0]=y0

    #generate the white noise
    eps=npr.randn(M-1)*np.sqrt(var)

    #increment the y vector
    for k in range(1,T):
        y[k]=corr*y[k-1]+eps[k-1]

    yy[j]=y

list.append(y)

Potrei usare qualche spiegazione per legare meglio questo alla domanda originale.
Erica
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.