Questa soluzione implementa un suggerimento fatto da @Innuo in un commento alla domanda:
È possibile mantenere un sottoinsieme casuale uniformemente campionato di dimensioni 100 o 1000 da tutti i dati visti finora. Questo set e le "recinzioni" associate possono essere aggiornate in volta.O ( 1 )
Una volta che sappiamo come mantenere questo sottoinsieme, possiamo selezionare qualsiasi metodo che ci piace per stimare la media di una popolazione da tale campione. Questo è un metodo universale, senza fare alcuna ipotesi, che funzionerà con qualsiasi flusso di input con un'accuratezza che può essere prevista usando formule di campionamento statistico standard. (La precisione è inversamente proporzionale alla radice quadrata della dimensione del campione.)
Questo algoritmo accetta come input un flusso di dati una dimensione del campione e genera un flusso di campioni ciascuno dei quali rappresenta la popolazione . In particolare, per , è un semplice campione casuale di dimensione da (senza sostituzione).t = 1 , 2 , … , m s ( t ) X ( t ) = ( x ( 1 ) , x ( 2 ) , … , x ( t ) ) 1 ≤ i ≤ t s ( i ) m X ( t )x ( t ) , t = 1 , 2 , … ,ms ( t )X( t ) = ( x ( 1 ) , x ( 2 ) , … , x ( t ) )1 ≤ i ≤ ts ( i )mX( t )
Perché ciò accada, è sufficiente che ogni sottoinsieme -elemento di abbia pari possibilità di essere gli indici di in . Ciò implica la possibilità che sia in uguale a fornito .{ 1 , 2 , … , t } x s ( t ) x ( i ) , 1 ≤ i < t , s ( t ) m / t t ≥ mm{ 1 , 2 , ... , t }Xs ( t )x ( i ) , 1 ≤ i < t ,s ( t )m / tt ≥ m
All'inizio raccogliamo solo il flusso fino a quando elementi sono stati memorizzati. A quel punto esiste un solo campione possibile, quindi la condizione di probabilità è banalmente soddisfatta.m
L'algoritmo prende il sopravvento quando . Supponiamo induttivamente che sia un semplice campione casuale di per . Impostare provvisoriamente . Sia una variabile casuale uniforme (indipendente da qualsiasi variabile precedente utilizzata per costruire ). Se sostituisce un elemento di scelto casualmente con . Questa è l'intera procedura!s ( t ) X ( t ) t > m s ( t + 1 ) = s ( t ) U ( t + 1 ) s ( t ) U ( t + 1 ) ≤ m / ( t + 1 ) s x ( t + 1 )t = m + 1s ( t )X( t )t>ms(t+1)=s(t)U(t+1)s(t)U(t+1)≤m/(t+1)sx(t+1)
Chiaramente ha probabilità di essere in . Inoltre, per l'ipotesi di induzione, aveva probabilità di essere in quando . Con probabilità = sarà stato rimosso da , da cui la sua probabilità di rimanere ugualem / ( t + 1 ) s ( t + 1 ) x ( i ) m / t s ( t ) i ≤ t m / ( t + 1 ) × 1 / m 1 / ( t + 1 ) s ( t + 1 )x(t+1)m/(t+1)s ( t + 1 )x ( i )m / ts ( t )i≤tm/(t+1)×1/m1/(t+1)s(t+1)
mt(1−1t+1)=mt+1,
esattamente come necessario. Per induzione, quindi, tutte le probabilità di inclusione di in sono corrette ed è chiaro che non esiste alcuna correlazione speciale tra tali inclusioni. Ciò dimostra che l'algoritmo è corretto.s ( t )x(i)s(t)
L'efficienza dell'algoritmo è perché in ogni fase vengono calcolati al massimo due numeri casuali e al massimo viene sostituito un elemento di un array di valori . Il requisito di archiviazione è .m O ( m )O(1)mO(m)
La struttura dei dati per questo algoritmo è costituita dai campioni insieme all'indice della popolazione che campiona. Inizialmente prendiamo e procediamo con l'algoritmo per Ecco un'implementazione per aggiornare con un valore per produrre . (L'argomento gioca il ruolo di ed è . L'indice verrà mantenuto dal chiamante.)t X ( t ) s = X ( m ) t = m + 1 , m + 2 , … . ( s , t ) x ( s , t + 1 ) t m tstX(t)s=X(m)t=m+1,m+2,….R
(s,t)x(s,t+1)n
tsample.size
mt
update <- function(s, x, n, sample.size) {
if (length(s) < sample.size) {
s <- c(s, x)
} else if (runif(1) <= sample.size / n) {
i <- sample.int(length(s), 1)
s[i] <- x
}
return (s)
}
Per illustrare e testare questo, userò il solito (non robusto) stimatore della media e confronterò la media stimata da con la media effettiva di (l'insieme cumulativo di dati visto ad ogni passaggio ). Ho scelto un flusso di input un po 'difficile che cambia in modo abbastanza regolare ma periodicamente subisce salti drammatici. La dimensione del campione di è abbastanza piccola, permettendoci di vedere le fluttuazioni di campionamento in questi grafici.X ( t ) m = 50s(t)X(t)m=50
n <- 10^3
x <- sapply(1:(7*n), function(t) cos(pi*t/n) + 2*floor((1+t)/n))
n.sample <- 50
s <- x[1:(n.sample-1)]
online <- sapply(n.sample:length(x), function(i) {
s <<- update(s, x[i], i, n.sample)
summary(s)})
actual <- sapply(n.sample:length(x), function(i) summary(x[1:i]))
A questo punto online
è la sequenza delle stime medie prodotte mantenendo questo campione corrente di valori mentre è la sequenza delle stime medie prodotte da tutti i dati disponibili in ogni momento. Il grafico mostra i dati (in grigio), (in nero) e due applicazioni indipendenti di questa procedura di campionamento (a colori). L'accordo è all'interno dell'errore di campionamento previsto:50actual
actual
plot(x, pch=".", col="Gray")
lines(1:dim(actual)[2], actual["Mean", ])
lines(1:dim(online)[2], online["Mean", ], col="Red")
Per stimatori affidabili della media, si prega di cercare nel nostro sito termini anomali e termini correlati. Tra le possibilità che vale la pena considerare ci sono le medie Winsorized e gli stimatori M.