Perché numpy std () fornisce un risultato diverso a matlab std ()?


88

Provo a convertire il codice matlab in numpy e ho capito che numpy ha un risultato diverso con la funzione std.

in matlab

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

in numpy

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

È normale? E come dovrei gestirlo?

Risposte:


146

La funzione NumPy np.stdaccetta un parametro opzionale ddof: "Delta Degrees of Freedom". Per impostazione predefinita, questo è 0. Impostalo su 1per ottenere il risultato MATLAB:

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

Per aggiungere un po 'più di contesto, nel calcolo della varianza (di cui la deviazione standard è la radice quadrata) tipicamente dividiamo per il numero di valori che abbiamo.

Ma se selezioniamo un campione casuale di Nelementi da una distribuzione più ampia e calcoliamo la varianza, la divisione per Npuò portare a una sottostima della varianza effettiva. Per risolvere questo problema, possiamo ridurre il numero per cui dividiamo ( i gradi di libertà ) a un numero inferiore a N(di solito N-1). Il ddofparametro ci consente di modificare il divisore per l'importo specificato.

Salvo diversa indicazione, NumPy calcolerà lo stimatore distorto per la varianza ( ddof=0, dividendo per N). Questo è ciò che vuoi se stai lavorando con l'intera distribuzione (e non un sottoinsieme di valori che sono stati scelti casualmente da una distribuzione più ampia). Se il ddofparametro viene fornito, NumPy divide N - ddofinvece per.

Il comportamento predefinito di MATLAB stdè correggere il bias per la varianza del campione dividendo per N-1. Questo elimina alcuni (ma probabilmente non tutti) i pregiudizi nella deviazione standard. Questo è probabilmente quello che vuoi se stai usando la funzione su un campione casuale di una distribuzione più ampia.

La bella risposta di @hbaderts fornisce ulteriori dettagli matematici.


4
Aggiungerò che in Matlab std([1 3 4 6],1)è equivalente al valore predefinito di NumPy np.std([1,3,4,6]). Tutto questo è spiegato abbastanza chiaramente nella documentazione per Matlab e NumPy, quindi consiglio vivamente che l'OP si assicuri di leggerli in futuro.
horchler

Ad un certo punto questo standard è cambiato: np.std () = np.std (ddof = 1), anche se la documentazione dice che np.std () dovrebbe essere impostato su ddof = 0 ...
ColinMac

61

La deviazione standard è la radice quadrata della varianza. La varianza di una variabile casuale Xè definita come

definizione di varianza

Uno stimatore per la varianza sarebbe quindi

stimatore distorto

dove campione medioindica la media del campione. Per selezionati casualmente xi, si può dimostrare che questo stimatore non converge alla varianza reale, ma a

stimatore imparziale

Se si selezionano campioni casualmente e si stima la media e la varianza del campione, sarà necessario utilizzare uno stimatore corretto (imparziale)

stimatore imparziale

che convergeranno a sigma quadrato. Il termine di correzione n-1è anche chiamato correzione di Bessel.

Ora, per impostazione predefinita, MATLABs stdcalcola lo stimatore imparziale con il termine di correzione n-1. NumPy tuttavia (come spiegato da @ajcr) calcola per impostazione predefinita lo stimatore distorto senza termine di correzione. Il parametro ddofpermette di impostare qualsiasi termine di correzione n-ddof. Impostandolo a 1 si ottiene lo stesso risultato di MATLAB.

Allo stesso modo, MATLAB permette di aggiungere un secondo parametro w, che specifica lo "schema di pesatura". L'impostazione predefinita,, w=0risulta nel termine di correzione n-1(stimatore imparziale), mentre per w=1, solo n viene utilizzato come termine di correzione (stimatore distorto).


2
Nella formula per lo stimatore corretto, il fattore n (all'interno della somma) non dovrebbe essere presente.
Frunobulax

3
L'intuizione alla base del termine n-1 nella varianza: hai già utilizzato i tuoi campioni per stimare la media che utilizzerai per approssimare la varianza. Questo introduce una correlazione e quindi ddof deve essere 1.
Matthias

@Frunobulax ho corretto l'errore di battitura per i posteri. Quello che è successo nell'equazione originale era che il limite superiore della somma non veniva riprodotto correttamente. Invece di nandare all'inizio della notazione di sommatoria, è andato all'interno della somma.
rayryeng

5

Per le persone che non sono brave con le statistiche, una guida semplicistica è:

  • Includi ddof=1se stai calcolando np.std()per un campione tratto dal tuo set di dati completo.

  • Assicurati ddof=0di eseguire il calcolo np.std()per l'intera popolazione

Il DDOF è incluso per i campioni al fine di controbilanciare il bias che può verificarsi nei numeri.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.