Estimativa online de variação com memória limitada

7

Estou criando um componente que visa calcular a média e a variação de uma métrica associada a eventos que ocorrem durante o tempo, mas com uma memória interna limitada.

Imagine que os eventos são visitantes que entram em uma loja e a métrica é a idade deles.

Durante o tempo, meu componente recebe eventos com a idade de cada visitante. Não quero que meu componente memorize a história de cada idade. Idealmente, eu gostaria de armazenar apenas um componente leve: a média A, a variação V e o número de eventos N.

Após cada evento com a idade E, desejo atualizar esses três valores:

N<=N+1
A<=(A*N+E)/(N+1)
V<=???

Para que V? Estou pensando em algo como:

V<=(V*N+(E-A)^2)/(N+1)

Eu sei que não é exato, pois o meu anterior Vestá usando o antigo, Aque não é mais a média.

Q1 - Existe uma fórmula exata?
Q2 - Se não, minha proposta é uma boa estimativa? É tendencioso? Irá convergir corretamente quando Naumentar?
Q3 - Existe uma fórmula melhor?

Arnaud Mégret
fonte
A precisão numérica também pode ser uma preocupação. E veja também Algoritmo online para calcular a variação com uma deterioração .
Scortchi - Restabelece Monica
Você também pode manter a soma de E ^ 2?
Andy W
Sim, tudo bem. I podem manter um número finito de valores, mas não dependendo de N.
Arnaud Mégret
4
Use um algoritmo de atualização de variação de passagem única numericamente estável, conforme fornecido, por exemplo, na seção 1 de cs.yale.edu/publications/techreports/tr222.pdf . A resposta de Andy W. é um método terrível, que pode ser muito impreciso.
Mark L. Stone

Respostas:

10

Um algoritmo agradável e simples para a variância computacional da maneira online foi descrito por Welford (1962). Abaixo, você pode ver a implementação em C ++ / Rcpp que funciona offline, mas pode ser facilmente adaptada ao cenário online:

List welford_cpp(NumericVector x) {

  int n = x.length();
  double delta;
  double msq = 0;
  double mean = x[0];

  if (n > 1) {
    for (int i = 1; i < n; i++) { 
      delta = x[i] - mean;
      mean += delta / (i+1);
      msq += delta * (x[i] - mean);
    }
    return Rcpp::List::create(Rcpp::Named("mean") = mean,
                              Rcpp::Named("variance") = msq / (n-1));
  }

  return Rcpp::List::create(Rcpp::Named("mean") = mean,
                            Rcpp::Named("variance") = NAN);
}

Como você pode ver, ele precisa armazenar apenas quatro variáveis: n, delta, msqe meane calcula média e variância, simultaneamente, como você queria.


Welford, BP (1962). Observe um método para calcular somas corrigidas de quadrados e produtos . Technometrics 4 (3): 419-420.

Tim
fonte
Muito bom, obrigado (a Mark Stone também pela referência). Excluirá minha resposta.
Andy W
1

A variância pode ser expressa como proporcional à diferença ao quadrado entre cada valor e o valor médio, ou (como muitos threads aqui em stats.SE documentados, como esta resposta que escrevi para outra pergunta) ela pode ser expressa como proporcional ao quadrado diferença de pares entre cada amostra.

Então sabemos:

Var(x)=1ni(XiX¯)2=12n2i,j(XiXj)2

Digamos que você adicione outra amostra, indexada como o último índice, . Sua variação anterior seria:k

Varold(x)=12(n1)2i<k,j<k(XiXj)2

Sua nova variação é

Varnew(x)=12n2i,j(XiXj)2=12n2(i<k,j<k(XiXj)2+j<k(XkXj)2+i<k(XiXk)2)

Mas

j<k(XkXj)2=i<k(XiXk)2i<k,j<k(XiXj)2=2(n1)2Varold(x)

assim

Varnew(x)=(n1n)2Varold(x)+1n2j<k(XkXj)2

Como o @ MarkL.Stone disse nos comentários, isso ainda não é eficiente, porque devemos manter todos os . Então, vamos expandir a fórmula para chegar a algo mais tratável.Xi

1n2j<k(XkXj)2=1n2j<k(Xk22XjXk+Xj2)=1n2(j<kXk22Xkj<kXj+j<kXj2)=1n2(kXk22Xk(k1)Xold¯+(k1)Xold2¯)
Porque
j<kXj=(k1)Xold¯j<kXj2=(k1)Xold2¯

O formulário final é então

Varnew(x)=(n1n)2Varold(x)+1n2(kXk22Xk(k1)Xold¯+(k1)Xold2¯)

Você pode usar esta fórmula para atualizar a variação efetivamente em memória. Você também pode complementá-lo para usar lotes em vez de atualizações de ponto único.

Basicamente, você precisa armazenar a média, a média das amostras ao quadrado e a variação a cada iteração e usá-la para atualizar a fórmula de variação.


Mais longe

Xold2¯=Varold(x)+(Xold¯)2Varnew(x)=(n1n)2Varold(x)+1n2(kXk22Xk(k1)Xold¯+(k1)(Varold(x)+(Xold¯)2))

O que reduz o número de quantidades que precisam ser armazenadas para 2.

Firebug
fonte
Este método não exige a disponibilidade de todos os pontos de dados anteriores para calcular a atualização? Nesse caso, isso contraria a idéia de lidar com a memória limitada. Observe que os algoritmos de atualização on-line, de acordo com as linhas de Welford na resposta de @Tim, que é uma instância específica de uma classe de algoritmos similares discutidos em cs.yale.edu/publications/techreports/tr222.pdf, não exigem salvar os antigos pontos de dados, mas apenas 2 registros (variáveis ​​escalares) para reter informações antigas.
Mark L. Stone
@ MarkL.Stone Hmm eu vejo. Sim, isso requer todos os valores anteriores , você está certo. Xi
Firebug
@ MarkL.Stone Atualizei a fórmula para que três escalares precisem ser armazenados. Eu já posso ver que pode ser reduzido ainda mais, talvez seja equivalente à outra solução.
Firebug
Devido à subtração, em vez de adicionar apenas quantidades não-negativas, o algoritmo revisado é menos numericamente preciso (robusto) que o Welford e algoritmos similares. Não vejo nenhum mérito nisso.
Mark L. Stone
0

OK, Andy W deu a resposta. Conservando a média da mesma maneira que a média E, você pode usar .E2V=exp(E2)exp(E)2

Arnaud Mégret
fonte
2
Por , você quer dizer o valor esperado de ? (E, não a função exponencial.)exp(E2)E2
Andy W
8
Esse método é bom, a menos que você se preocupe em obter a resposta certa.
Mark L. Stone
2
Instabilidade numérica e, portanto, imprecisão numérica. É correto se for executado na aritmética exata, ou seja, precisão infinita. Em precisão finita em um computador, ele pode ser muito imprecisa, e pode até mesmo sair negativo (e realmente tem em muitas ocasiões) ..
Mark L. Stone
4
O Excel realmente usou esse método por um longo tempo (para muitas críticas e escárnio de estatísticos e outros). Em circunstâncias bastante simples (dados com média grande, pequeno desvio padrão), você poderia fazer com que sua função de variação desse resultado correspondesse a uma aproximação de um gerador de números aleatórios (altere os dados por pequenas quantidades sucessivas e a variação relatada saltou drasticamente). Isso foi causado pelo cancelamento catastrófico da diferença. Foi uma maneira muito eficaz de demonstrar por que esses problemas são importantes. O Excel não faz mais isso.
Glen_b -Reinstate Monica
4
Sobre esse cancelamento catastrófico, veja, por exemplo, a discussão aqui
Glen_b -Reinstate Monica 15/09/16