Die Antwort von Jason R weist einen Fehler auf, der in Knuths "Art of Computer Programming" vol. 2. Das Problem tritt auf, wenn Sie eine Standardabweichung haben, die einen kleinen Bruchteil des Mittelwerts darstellt: Die Berechnung von E (x ^ 2) - (E (x) ^ 2) ist sehr empfindlich gegenüber Gleitkomma-Rundungsfehlern.
Sie können dies sogar selbst in einem Python-Skript versuchen:
ofs = 1e9
A = [ofs+x for x in [1,-1,2,3,0,4.02,5]]
A2 = [x*x for x in A]
(sum(A2)/len(A))-(sum(A)/len(A))**2
Ich erhalte -128.0 als Antwort, was eindeutig nicht rechnerisch gültig ist, da die Mathematik vorhersagt, dass das Ergebnis nicht negativ sein sollte.
Knuth zitiert einen Ansatz (ich erinnere mich nicht an den Namen des Erfinders) zur Berechnung des laufenden Mittelwerts und der Standardabweichung, der ungefähr so aussieht:
initialize:
m = 0;
S = 0;
n = 0;
for each incoming sample x:
prev_mean = m;
n = n + 1;
m = m + (x-m)/n;
S = S + (x-m)*(x-prev_mean);
und dann ist der Wert von nach jedem Schritt m
der Mittelwert, und die Standardabweichung kann als sqrt(S/n)
oder sqrt(S/n-1)
abhängig davon berechnet werden, welche Ihre bevorzugte Definition der Standardabweichung ist.
Die Gleichung, die ich oben schreibe, unterscheidet sich geringfügig von der in Knuth, ist jedoch rechnerisch äquivalent.
Wenn ich noch ein paar Minuten Zeit habe, codiere ich die obige Formel in Python und zeige, dass Sie eine nicht negative Antwort erhalten (die hoffentlich nahe am richtigen Wert liegt).
update: hier ist es.
test1.py:
import math
def stats(x):
n = 0
S = 0.0
m = 0.0
for x_i in x:
n = n + 1
m_prev = m
m = m + (x_i - m) / n
S = S + (x_i - m) * (x_i - m_prev)
return {'mean': m, 'variance': S/n}
def naive_stats(x):
S1 = sum(x)
n = len(x)
S2 = sum([x_i**2 for x_i in x])
return {'mean': S1/n, 'variance': (S2/n - (S1/n)**2) }
x1 = [1,-1,2,3,0,4.02,5]
x2 = [x+1e9 for x in x1]
print "naive_stats:"
print naive_stats(x1)
print naive_stats(x2)
print "stats:"
print stats(x1)
print stats(x2)
Ergebnis:
naive_stats:
{'variance': 4.0114775510204073, 'mean': 2.0028571428571427}
{'variance': -128.0, 'mean': 1000000002.0028572}
stats:
{'variance': 4.0114775510204073, 'mean': 2.0028571428571431}
{'variance': 4.0114775868357446, 'mean': 1000000002.0028571}
Sie werden feststellen, dass es immer noch einige Rundungsfehler gibt, aber es ist nicht schlecht, während naive_stats
nur Kotzen.
Bearbeiten: Gerade bemerkt, dass Belisarius Wikipedia zitiert, in dem der Knuth-Algorithmus erwähnt wird.