Warum gibt numpy std () ein anderes Ergebnis als matlab std ()?

85

Ich versuche, Matlab-Code in numpy zu konvertieren und habe herausgefunden, dass numpy mit der std-Funktion ein anderes Ergebnis hat.

in matlab

std([1,3,4,6])
ans =  2.0817

in numpy

np.std([1,3,4,6])
1.8027756377319946

Ist das normal? Und wie soll ich damit umgehen?

Gustavgans
quelle

Antworten:

144

Die NumPy-Funktion np.stdakzeptiert einen optionalen Parameter ddof: "Delta Degrees of Freedom". Standardmäßig ist dies 0. Stellen Sie es auf ein 1, um das MATLAB-Ergebnis zu erhalten:

>>> np.std([1,3,4,6], ddof=1)
2.0816659994661326

Um etwas mehr Kontext hinzuzufügen, dividieren wir bei der Berechnung der Varianz (deren Standardabweichung die Quadratwurzel ist) normalerweise durch die Anzahl der Werte, die wir haben.

Wenn wir jedoch eine zufällige Stichprobe von NElementen aus einer größeren Verteilung auswählen und die Varianz berechnen, Nkann die Division durch zu einer Unterschätzung der tatsächlichen Varianz führen. Um dies zu beheben, können wir die Zahl, die wir durch ( die Freiheitsgrade ) teilen, auf eine Zahl senken, die kleiner als N(normalerweise N-1) ist. Mit dem ddofParameter können wir den Divisor um den von uns angegebenen Betrag ändern.

Sofern nicht anders angegeben, berechnet NumPy den voreingenommenen Schätzer für die Varianz ( ddof=0dividiert durch N). Dies ist das, was Sie möchten, wenn Sie mit der gesamten Verteilung arbeiten (und nicht mit einer Teilmenge von Werten, die zufällig aus einer größeren Verteilung ausgewählt wurden). Wenn der ddofParameter angegeben ist, wird N - ddofstattdessen NumPy durch dividiert .

Das Standardverhalten von MATLABs stdbesteht darin, die Abweichung für die Stichprobenvarianz durch Teilen durch zu korrigieren N-1. Dadurch werden einige (aber wahrscheinlich nicht alle) Abweichungen in der Standardabweichung beseitigt. Dies ist wahrscheinlich das, was Sie möchten, wenn Sie die Funktion für eine Zufallsstichprobe einer größeren Verteilung verwenden.

Die nette Antwort von @hbaderts gibt weitere mathematische Details.

Alex Riley
quelle
4
Ich werde hinzufügen, dass in Matlab, std([1 3 4 6],1)entspricht NumPy Standard np.std([1,3,4,6]). All dies wird in der Dokumentation für Matlab und NumPy ganz klar erklärt. Ich empfehle daher dringend, dass das OP diese in Zukunft unbedingt liest.
Horchler
Irgendwann hat sich dieser Standard geändert: np.std () = np.std (ddof = 1), obwohl die Dokumentation besagt, dass np.std () standardmäßig ddof = 0 sein sollte ...
ColinMac
60

Die Standardabweichung ist die Quadratwurzel der Varianz. Die Varianz einer Zufallsvariablen Xist definiert als

Definition der Varianz

Ein Schätzer für die Varianz wäre daher

voreingenommener Schätzer

wobei Stichprobenmittelwertbezeichnet den Stichprobenmittelwert. Für zufällig ausgewählte xikann gezeigt werden, dass dieser Schätzer nicht zur realen Varianz konvergiert, sondern zu

unvoreingenommener Schätzer

Wenn Sie Stichproben zufällig auswählen und den Stichprobenmittelwert und die Varianz schätzen, müssen Sie einen korrigierten (unverzerrten) Schätzer verwenden

unvoreingenommener Schätzer

was zu konvergieren wird Sigma im Quadrat. Der Korrekturterm n-1wird auch als Besselsche Korrektur bezeichnet.

Jetzt werden standardmäßig MATLABs stdberechnet den unvoreingenommenen Schätzer mit dem Korrekturterm n-1. NumPy berechnet jedoch (wie @ajcr erklärt) den voreingenommenen Schätzer standardmäßig ohne Korrekturterm. Mit dem Parameter ddofkönnen Sie einen beliebigen Korrekturterm einstellen n-ddof. Wenn Sie den Wert auf 1 setzen, erhalten Sie das gleiche Ergebnis wie in MATLAB.

In ähnlicher Weise ermöglicht MATLAB das Hinzufügen eines zweiten Parameters w, der das "Wiegeschema" angibt. Der Standardwert ,, w=0ergibt den Korrekturterm n-1(unverzerrter Schätzer), während für w=1nur n als Korrekturterm (voreingenommener Schätzer) verwendet wird.

hbaderts
quelle
2
In der Formel für den korrigierten Schätzer sollte der Faktor n (innerhalb der Summe) nicht vorhanden sein.
Frunobulax
3
Die Intuition hinter dem n-1-Term in der Varianz: Sie haben Ihre Stichproben bereits zur Schätzung des Mittelwerts verwendet, den Sie zur Approximation der Varianz verwenden werden. Dies führt eine Korrelation ein und daher muss ddof 1 sein.
Matthias
@Frunobulax Ich habe den Tippfehler für die Nachwelt behoben. Was in der ursprünglichen Gleichung geschah, war, dass die Obergrenze der Summe nicht richtig gerendert wurde. Anstatt noben in der Summationsnotation zu stehen, ging es in die Summe.
Rayryeng
4

Für Leute, die nicht gut mit Statistiken umgehen können, ist ein vereinfachter Leitfaden:

  • Schließen ddof=1Sie ein, wenn Sie np.std()eine Stichprobe aus Ihrem vollständigen Datensatz berechnen .

  • Stellen ddof=0Sie sicher, dass Sie np.std()für die gesamte Bevölkerung rechnen

Der DDOF ist für Abtastwerte enthalten, um die Vorspannung auszugleichen, die in den Zahlen auftreten kann.

MJM
quelle