Online-Varianzschätzung mit begrenztem Speicher


7

Ich erstelle eine Komponente, die darauf abzielt, den Durchschnitt und die Varianz einer Metrik zu berechnen, die mit Ereignissen verbunden ist, die während der Zeit auftreten, aber mit einem begrenzten internen Speicher.

Stellen Sie sich vor, die Ereignisse sind Besucher, die einen Laden betreten, und die Metrik entspricht ihrem Alter.

Im Laufe der Zeit erhält meine Komponente Ereignisse mit dem Alter jedes Besuchers. Ich möchte nicht, dass meine Komponente die Geschichte jedes Zeitalters auswendig lernt. Idealerweise möchte ich nur eine leichte Komponente speichern: den Durchschnitt A, die Varianz V und die Anzahl der Ereignisse N.

Nach jedem Ereignis mit dem Alter Emöchte ich diese drei Werte aktualisieren:

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

Wofür V? Ich denke an etwas wie:

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

Ich weiß, dass es nicht genau ist, da mein Vorgänger Vdas Alte verwendet, Awas nicht mehr der Durchschnitt ist.

Q1 - Gibt es eine genaue Formel?
F2 - Wenn nicht, ist mein Vorschlag eine gute Schätzung? Ist es voreingenommen? Konvergiert es korrekt, wenn es Nzunimmt?
Q3 - Gibt es eine bessere Formel?


Die numerische Genauigkeit könnte ebenfalls ein Problem sein. Siehe auch Online-Algorithmus zur Berechnung der Varianz mit einem Zerfall .
Scortchi - Monica wieder einsetzen

Können Sie auch die Summe von E ^ 2 behalten?
Andy W

Ja, es wäre in Ordnung. Ich kann eine endliche Anzahl von Werten behalten, aber nicht abhängig von N.
Arnaud Mégret

4
Verwenden Sie einen numerisch stabilen Algorithmus zur Aktualisierung der Varianz in einem Durchgang, wie beispielsweise in Abschnitt 1 von cs.yale.edu/publications/techreports/tr222.pdf beschrieben . Die Antwort von Andy W. ist eine schreckliche Methode, die sehr ungenau sein kann.
Mark L. Stone

Antworten:


10

Ein guter und einfacher Algorithmus zur Online-Berechnung der Varianz wurde von Welford (1962) beschrieben. Unten sehen Sie die C ++ / Rcpp-Implementierung, die offline funktioniert, aber leicht an das Online-Szenario angepasst werden kann:

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);
}

Wie Sie sehen können, braucht es nur vier Variablen speichern: n, delta, msqund meanund berechnet Mittelwert und die Varianz gleichzeitig , wie man wollte.


Welford, BP (1962). Hinweis zu einer Methode zur Berechnung korrigierter Summen von Quadraten und Produkten . Technometrics 4 (3): 419 & ndash; 420.


Sehr schön, danke (auch an Mark Stone für den Hinweis). Löscht meine Antwort.
Andy W

1

Die Varianz kann als proportional zur quadratischen Differenz zwischen jedem Wert und dem Mittelwert ausgedrückt werden oder (wie viele Threads hier in stats.SE dokumentiert sind, wie diese Antwort, die ich auf eine andere Frage geschrieben habe) alternativ als proportional zum Quadrat ausgedrückt werden paarweiser Unterschied zwischen jeder Probe.

Wir wissen also:

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

Angenommen, Sie fügen ein weiteres Beispiel hinzu, das als letzter Index indiziert ist, . Ihre vorherige Abweichung wäre:k

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

Ihre neue Varianz ist

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

Aber

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

Damit

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

Wie @ MarkL.Stone in den Kommentaren sagte, ist dies immer noch nicht effizient, da wir jedes behalten müssen . Erweitern wir also die Formel, um zu etwas Traktablerem zu gelangen.Xi

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

Die endgültige Form ist dann

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

Sie können diese Formel verwenden, um die Varianz in Bezug auf den Speicher effektiv zu aktualisieren. Sie können es auch ergänzen, um Stapel anstelle von Einzelpunktaktualisierungen zu verwenden.

Grundsätzlich müssen Sie den Durchschnitt, den Durchschnitt der quadratischen Stichproben und die Varianz bei jeder Iteration speichern und zum Aktualisieren der Varianzformel verwenden.


Des Weiteren

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

Dies reduziert die Anzahl der Mengen, die gelagert werden müssen, auf 2.


Erfordert diese Methode nicht die Verfügbarkeit aller vorherigen Datenpunkte, um das Update zu berechnen? Wenn ja, widerspricht dies der Idee, mit begrenztem Gedächtnis umzugehen. Beachten Sie, dass Online-Aktualisierungsalgorithmen nach dem Vorbild von Welford in der Antwort von @Tim, einer bestimmten Instanz einer Klasse ähnlicher Algorithmen, die in cs.yale.edu/publications/techreports/tr222.pdf beschrieben werden, kein Speichern von alten Algorithmen erfordern Datenpunkte, aber nur 2 Register (skalare Variablen), um alte Informationen beizubehalten.
Mark L. Stone

@ MarkL.Stone Hmm ich verstehe. Ja, dies erfordert alle vorherigen Werte , Sie haben Recht. Xi
Firebug

@ MarkL.Stone Ich habe die Formel aktualisiert, sodass drei Skalare gespeichert werden müssen. Ich kann bereits sehen, dass es weiter reduziert werden kann, vielleicht gleichwertig mit der anderen Lösung.
Firebug

Aufgrund der Subtraktion ist Ihr überarbeiteter Algorithmus nicht nur nicht negative Größen addierend, sondern auch numerisch weniger genau (robust) als der Welford-Algorithmus und ähnliche Algorithmen. Ich sehe darin überhaupt keinen Verdienst.
Mark L. Stone

0

OK Andy W gab die Antwort. Indem Sie den Durchschnitt auf die gleiche Weise wie den E-Durchschnitt , können Sie .E2V=exp(E2)exp(E)2


2
Mit meinen Sie vielleicht den erwarteten Wert von ? (Und nicht die Exponentialfunktion.)exp(E2)E2
Andy W

8
Diese Methode ist in Ordnung, es sei denn, Sie möchten die richtige Antwort erhalten.
Mark L. Stone

2
Numerische Instabilität und damit numerische Ungenauigkeit. Es ist richtig, wenn es in exakter Arithmetik ausgeführt wird, dh mit unendlicher Genauigkeit. In endlicher Präzision auf einem Computer kann es sehr ungenau sein und sogar negativ ausfallen (und hat es tatsächlich bei vielen Gelegenheiten).
Mark L. Stone

4
Excel hat diese Methode tatsächlich lange Zeit verwendet (zu viel Kritik und Spott von Statistikern und anderen). Unter ganz einfachen Umständen (Daten mit großem Mittelwert, kleiner Standardabweichung) können Sie die Varianzfunktion so einstellen, dass sie eine Ausgabe liefert, die einer Annäherung eines Zufallszahlengenerators entspricht (verschieben Sie die Daten um aufeinanderfolgende kleine Beträge, und die gemeldete Varianz springt dramatisch herum). Dies wurde durch eine katastrophale Aufhebung der Differenz verursacht. Dies war ein sehr effektiver Weg, um zu demonstrieren, warum diese Probleme wichtig sind. Excel macht das nicht mehr.
Glen_b -State Monica

4
Zu dieser katastrophalen Absage siehe zum Beispiel die Diskussion hier
Glen_b -Reinstate Monica
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.