Dlaczego numpy std () daje inny wynik matlab std ()?

87

Próbuję przekonwertować kod Matlab na numpy i odkryłem, że numpy ma inny wynik z funkcją std.

w matlab

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

w numpy

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

Czy to normalne? Jak mam sobie z tym poradzić?

gustavgans
źródło

Odpowiedzi:

145

Funkcja NumPy np.stdprzyjmuje opcjonalny parametr ddof: „Delta Degrees of Freedom”. Domyślnie jest to 0. Ustaw go na, 1aby uzyskać wynik MATLAB:

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

Aby dodać trochę więcej kontekstu, podczas obliczania wariancji (której odchylenie standardowe jest pierwiastkiem kwadratowym) zazwyczaj dzielimy przez liczbę posiadanych wartości.

Ale jeśli wybierzemy losową próbkę Nelementów z większego rozkładu i obliczymy wariancję, dzielenie przez Nmoże prowadzić do niedoszacowania rzeczywistej wariancji. Aby to naprawić, możemy obniżyć liczbę, którą dzielimy ( stopnie swobody ) do liczby mniejszej niż N(zwykle N-1). ddofParametr pozwala nam zmienić dzielnik o kwotę możemy określić.

O ile nie podano inaczej, NumPy obliczy obciążony estymator dla wariancji ( ddof=0dzieląc przez N). To jest to, czego potrzebujesz, jeśli pracujesz z całym rozkładem (a nie podzbiorem wartości, które zostały losowo wybrane z większego rozkładu). Jeśli ddofpodano parametr, NumPy dzieli N - ddofzamiast tego.

Domyślnym zachowaniem MATLAB-ów stdjest skorygowanie odchylenia dla wariancji próbki przez podzielenie przez N-1. Pozwala to pozbyć się części (ale prawdopodobnie nie wszystkich) błędu odchylenia standardowego. To prawdopodobnie jest to, czego chcesz, jeśli używasz funkcji na losowej próbce większej dystrybucji.

Miła odpowiedź @hbaderts podaje dalsze matematyczne szczegóły.

Alex Riley
źródło
4
Dodam, że w Matlabie std([1 3 4 6],1)jest odpowiednikiem domyślnego NumPy np.std([1,3,4,6]). Wszystko to jest dość jasno wyjaśnione w dokumentacji dla Matlab i NumPy, więc zdecydowanie zalecam, aby OP, koniecznie zapoznał się z nimi w przyszłości.
horchler,
W pewnym momencie ten standard zmieniło: np.std () = np.std (ddof = 1), mimo że dokumentacja mówi, że np.std () powinna domyślnie ddof = 0 ...
ColinMac
61

Odchylenie standardowe to pierwiastek kwadratowy z wariancji. Wariancja zmiennej losowej Xjest definiowana jako

definicja wariancji

Zatem estymatorem wariancji byłby

estymator obciążony

gdzie próbka średniaoznacza średnią próbki. Dla losowo wybranych ximożna wykazać, że estymator ten nie jest zbieżny do wariancji rzeczywistej, ale do

bezstronny estymator

Jeśli losowo wybierzesz próbki i oszacujesz średnią próbki i wariancję, będziesz musiał użyć skorygowanego (nieobciążonego) estymatora

bezstronny estymator

które zbiegną się do sigma do kwadratu. Składnik korygujący n-1jest również nazywany poprawką Bessela.

Teraz MATLABs domyślnie stdoblicza nieobciążony estymator ze składnikiem korygującym n-1. Jednak NumPy (jak wyjaśnił @ajcr) domyślnie oblicza obciążony estymator bez składnika korekcyjnego. Parametr ddofumożliwia ustawienie dowolnego współczynnika korekcji n-ddof. Ustawiając go na 1, otrzymasz taki sam wynik jak w MATLAB.

Podobnie MATLAB pozwala na dodanie drugiego parametru wokreślającego „schemat ważenia”. Wartość domyślna, w=0powoduje powstanie składnika korygującego n-1(estymator nieobciążony), podczas gdy dla w=1, tylko n jest używane jako składnik korygujący (estymator obciążony).

hbaderts
źródło
2
We wzorze na skorygowany estymator czynnik n (w ramach sumy) nie powinien występować.
Frunobulax
3
Intuicja stojąca za składnikiem n-1 w wariancji: użyłeś już swoich próbek do oszacowania średniej, której użyjesz do aproksymacji wariancji. To wprowadza korelację i dlatego ddof musi wynosić 1.
Matthias
@Frunobulax Poprawiłem literówkę dla potomności. To, co wydarzyło się w pierwotnym równaniu, to górna granica sumy nie była renderowana poprawnie. Zamiast niść na górę notacji sumowania, wszedł do sumy.
rayryeng
4

Dla osób, które nie radzą sobie ze statystykami, uproszczony przewodnik to:

  • Uwzględnij, ddof=1jeśli obliczasz np.std()dla próbki pobranej z pełnego zbioru danych.

  • Upewnij się ddof=0, że obliczasz np.std()dla całej populacji

DDOF jest dołączany do próbek, aby zrównoważyć błąd, który może wystąpić w liczbach.

MJM
źródło