Riproduce la figura di "Inferenza statistica sull'era dei computer" di Efron e Hastie


8

La versione sintetizzata della mia domanda

(26 dicembre 2018)

Sto cercando di riprodurre Figura 2.2 dal computer Età Statistical Inference da Efron e Hastie, ma per qualche motivo che io non sono in grado di capire, i numeri non sono corrispondenti a quelli del libro.

Supponiamo che stiamo cercando di decidere tra due possibili funzioni di densità di probabilità per i dati osservati X, una densità di ipotesi nulla f0(X) e una densità alternativa f1(X). Una regola di provat(X) dice quale scelta, 0 o 1, faremo osservare i dati X. Ogni regola del genere ha due probabilità di errore frequentist associate: la sceltaf1 quando in realtà f0 generato X, e viceversa,

α=Prf0{t(X)=1},
β=Prf1{t(X)=0}.

Permettere L(X)essere il rapporto di verosimiglianza ,

L(X)=f1(X)f0(X)

Quindi, il lemma di Neyman-Pearson afferma che la regola di prova del modulo tc(X) è l'algoritmo di verifica delle ipotesi ottimale

tc(X)={1se registro L(X)c0se registro L(X)<c.

Per f0~N(0,1),f1~N(0.5,1)e dimensione del campione n=10 quali sarebbero i valori per α e β per un taglio c=0.4?

  • Dalla Figura 2.2 dell'Inferenza statistica sull'era dei computer di Efron e Hastie abbiamo:
    • α=0.10 e β=0.38 per un taglio c=0.4
  • ho trovato α=0.15 e β=0.30 per un taglio c=0.4usando due approcci diversi: A) simulazione e B) analiticamente .

Gradirei se qualcuno potesse spiegarmi come ottenere α=0.10 e β=0.38 per un taglio c=0.4. Grazie.

La versione sintetizzata della mia domanda finisce qui. Da adesso troverai:

  • Nella sezione A) dettagli e codice python completo del mio approccio di simulazione .
  • Nella sezione B) dettagli e codice python completo dell'approccio analitico .

A) Il mio approccio alla simulazione con codice e spiegazioni complete di Python

(20 dicembre 2018)

Dal libro ...

Nello stesso spirito, il lemma di Neyman-Pearson fornisce un algoritmo di verifica delle ipotesi ottimale. Questa è forse la più elegante delle costruzioni frequentiste. Nella sua formulazione più semplice, il lemma NP presuppone che stiamo cercando di decidere tra due possibili funzioni di densità di probabilità per i dati osservatiX, una densità di ipotesi nulla f0(X) e una densità alternativa f1(X). Una regola di provat(X) dice quale scelta, 0 o 1, faremo osservare i dati X. Ogni regola del genere ha due probabilità di errore frequentist associate: la sceltaf1 quando in realtà f0 generato X, e viceversa,

α=Prf0{t(X)=1},
β=Prf1{t(X)=0}.

Permettere L(X)essere il rapporto di verosimiglianza ,

L(X)=f1(X)f0(X)

(Fonte: Efron, B., & Hastie, T. (2016). Inferenza statistica sull'era dei computer: algoritmi, prove e scienza dei dati. Cambridge: Cambridge University Press. )

Quindi, ho implementato il codice Python di seguito ...

import numpy as np

def likelihood_ratio(x, f1_density, f0_density):
    return np.prod(f1_density.pdf(x)) / np.prod(f0_density.pdf(x))

Ancora una volta, dal libro ...

e definire la regola di prova tc(X) di

tc(X)={1se registro L(X)c0se registro L(X)<c.

(Fonte: Efron, B., & Hastie, T. (2016). Inferenza statistica sull'era dei computer: algoritmi, prove e scienza dei dati. Cambridge: Cambridge University Press. )

Quindi, ho implementato il codice Python di seguito ...

def Neyman_Pearson_testing_rule(x, cutoff, f0_density, f1_density):
    lr = likelihood_ratio(x, f1_density, f0_density)
    llr = np.log(lr)

    if llr >= cutoff:
        return 1
    else:
        return 0

Finalmente, dal libro ...

inserisci qui la descrizione dell'immagine

Dove è possibile concludere che un taglio c=0.4 implicherà α=0.10 e β=0.38.

Quindi, ho implementato il codice Python di seguito ...

def alpha_simulation(cutoff, f0_density, f1_density, sample_size, replicates):
    NP_test_results = []

    for _ in range(replicates):
        x = f0_density.rvs(size=sample_size)
        test = Neyman_Pearson_testing_rule(x, cutoff, f0_density, f1_density)
        NP_test_results.append(test)

    return np.sum(NP_test_results) / float(replicates)

def beta_simulation(cutoff, f0_density, f1_density, sample_size, replicates):
    NP_test_results = []

    for _ in range(replicates):
        x = f1_density.rvs(size=sample_size)
        test = Neyman_Pearson_testing_rule(x, cutoff, f0_density, f1_density)
        NP_test_results.append(test)

    return (replicates - np.sum(NP_test_results)) / float(replicates)

e il codice ...

from scipy import stats as st

f0_density = st.norm(loc=0, scale=1)
f1_density = st.norm(loc=0.5, scale=1)

sample_size = 10
replicates = 12000

cutoffs = []
alphas_simulated = []
betas_simulated = []
for cutoff in np.arange(3.2, -3.6, -0.4):
    alpha_ = alpha_simulation(cutoff, f0_density, f1_density, sample_size, replicates)
    beta_ = beta_simulation(cutoff, f0_density, f1_density, sample_size, replicates)

    cutoffs.append(cutoff)
    alphas_simulated.append(alpha_)
    betas_simulated.append(beta_)

e il codice ...

import matplotlib.pyplot as plt
%matplotlib inline

# Reproducing Figure 2.2 from simulation results.
plt.xlabel('$\\alpha$')
plt.ylabel('$\\beta$')
plt.xlim(-0.1, 1.05)
plt.ylim(-0.1, 1.05)
plt.axvline(x=0, color='b', linestyle='--')
plt.axvline(x=1, color='b', linestyle='--')
plt.axhline(y=0, color='b', linestyle='--')
plt.axhline(y=1, color='b', linestyle='--')
figure_2_2 = plt.plot(alphas_simulated, betas_simulated, 'ro', alphas_simulated, betas_simulated, 'k-')

per ottenere qualcosa del genere:

inserisci qui la descrizione dell'immagine

sembra simile alla figura originale del libro, ma le 3 tuple (c,α,β) dalla mia simulazione ha valori diversi di α e β rispetto a quelli del libro per lo stesso valore soglia c. Per esempio:

  • dal libro che abbiamo (c=0.4,α=0.10,β=0.38)
  • dalla mia simulazione abbiamo:
    • (c=0.4,α=0.15,β=0.30)
    • (c=0.8,α=0.10,β=0.39)

Sembra che il taglio c=0.8 dalla mia simulazione è equivalente al cutoff c=0.4 dal libro.

Gradirei se qualcuno potesse spiegarmi cosa sto facendo di sbagliato qui. Grazie.

B) Il mio approccio di calcolo con codice e spiegazioni complete di Python

(26 dicembre 2018)

Ancora cercando di capire la differenza tra i risultati della mia simulazione ( alpha_simulation(.), beta_simulation(.)) e quelli presentati nel libro, con l'aiuto di un mio statistico (Sofia) amico, abbiamo calcolatoα e β analiticamente invece che tramite simulazione, quindi ...

Una volta quello

f0~N(0,1)
f1~N(0.5,1)

poi

f(X|μ,σ2)=Πio=1n12πσ2e-(Xio-μ)22σ2

Inoltre,

L(X)=f1(X)f0(X)

così,

L(X)=f1(X|μ1,σ2)f0(X|μ0,σ2)=Πio=1n12πσ2e-(Xio-μ1)22σ2Πio=1n12πσ2e-(Xio-μ0)22σ2

Pertanto, eseguendo alcune semplificazioni algebriche (come sotto), avremo:

L(X)=(12πσ2)ne-Σio=1n(Xio-μ1)22σ2(12πσ2)ne-Σio=1n(Xio-μ0)22σ2

=e-Σio=1n(Xio-μ1)2+Σio=1n(Xio-μ0)22σ2

=e-Σio=1n(Xio2-2Xioμ1+μ12)+Σio=1n(Xio2-2Xioμ0+μ02)2σ2

=e-Σio=1nXio2+2μ1Σio=1nXio-Σio=1nμ12+Σio=1nXio2-2μ0Σio=1nXio+Σio=1nμ022σ2

=e2(μ1-μ0)Σio=1nXio+n(μ02-μ12)2σ2
.

Quindi se

tc(X)={1se registro L(X)c0se registro L(X)<c.

quindi, per log L(X)c avremo:

log (e2(μ1-μ0)Σio=1nXio+n(μ02-μ12)2σ2)c

2(μ1-μ0)Σio=1nXio+n(μ02-μ12)2σ2c

Σio=1nXio2cσ2-n(μ02-μ12)2(μ1-μ0)

Σio=1nXio2cσ22(μ1-μ0)-n(μ02-μ12)2(μ1-μ0)

Σio=1nXiocσ2(μ1-μ0)-n(μ02-μ12)2(μ1-μ0)

Σio=1nXiocσ2(μ1-μ0)+n(μ12-μ02)2(μ1-μ0)

Σio=1nXiocσ2(μ1-μ0)+n(μ1-μ0)(μ1+μ0)2(μ1-μ0)

Σio=1nXiocσ2(μ1-μ0)+n(μ1+μ0)2

(1n)Σio=1nXio(1n)(cσ2(μ1-μ0)+n(μ1+μ0)2)

Σio=1nXioncσ2n(μ1-μ0)+(μ1+μ0)2

X¯cσ2n(μ1-μ0)+(μ1+μ0)2

X¯K, dove K=cσ2n(μ1-μ0)+(μ1+μ0)2

con il risultato di

tc(X)={1Se X¯K0Se X¯<K., dove K=cσ2n(μ1-μ0)+(μ1+μ0)2

Per calcolare α e β, lo sappiamo:

α=Prf0{t(X)=1},
β=Prf1{t(X)=0}.

così,

α=Prf0{X¯K},β=Prf1{X¯<K}. dove K=cσ2n(μ1-μ0)+(μ1+μ0)2

Per α ...

α=Prf0{X¯K}=Prf0{X¯-μ0K-μ0}

α=Prf0{X¯-μ0σnK-μ0σn}

α=Prf0{z-scoreK-μ0σn} dove K=cσ2n(μ1-μ0)+(μ1+μ0)2

così, ho implementato il codice Python di seguito:

def alpha_calculation(cutoff, m_0, m_1, variance, sample_size):
    c = cutoff
    n = sample_size
    sigma = np.sqrt(variance)

    k = (c*variance)/(n*(m_1-m_0)) + (m_1+m_0)/2.0

    z_alpha = (k-m_0)/(sigma/np.sqrt(n))

    # Pr{z_score >= z_alpha}
    return 1.0 - st.norm(loc=0, scale=1).cdf(z_alpha)

Per β ...

β=Prf1{X¯<K}=Prf1{X¯-μ1<K-μ1}

β=Prf1{X¯-μ1σn<K-μ1σn}

β=Prf1{z-score<K-μ1σn} dove K=cσ2n(μ1-μ0)+(μ1+μ0)2

risultante nel codice Python di seguito:

def beta_calculation(cutoff, m_0, m_1, variance, sample_size):
    c = cutoff
    n = sample_size
    sigma = np.sqrt(variance)

    k = (c*variance)/(n*(m_1-m_0)) + (m_1+m_0)/2.0

    z_beta = (k-m_1)/(sigma/np.sqrt(n))

    # Pr{z_score < z_beta}
    return st.norm(loc=0, scale=1).cdf(z_beta)

e il codice ...

alphas_calculated = []
betas_calculated = []
for cutoff in cutoffs:
    alpha_ = alpha_calculation(cutoff, 0.0, 0.5, 1.0, sample_size)
    beta_ = beta_calculation(cutoff, 0.0, 0.5, 1.0, sample_size)

    alphas_calculated.append(alpha_)
    betas_calculated.append(beta_)

e il codice ...

# Reproducing Figure 2.2 from calculation results.
plt.xlabel('$\\alpha$')
plt.ylabel('$\\beta$')
plt.xlim(-0.1, 1.05)
plt.ylim(-0.1, 1.05)
plt.axvline(x=0, color='b', linestyle='--')
plt.axvline(x=1, color='b', linestyle='--')
plt.axhline(y=0, color='b', linestyle='--')
plt.axhline(y=1, color='b', linestyle='--')
figure_2_2 = plt.plot(alphas_calculated, betas_calculated, 'ro', alphas_calculated, betas_calculated, 'k-')

per ottenere una cifra e valori per α e β molto simile alla mia prima simulazione

inserisci qui la descrizione dell'immagine

E infine per confrontare i risultati tra simulazione e calcolo fianco a fianco ...

df = pd.DataFrame({
    'cutoff': np.round(cutoffs, decimals=2), 
    'simulated alpha': np.round(alphas_simulated, decimals=2),
    'simulated beta': np.round(betas_simulated, decimals=2),
    'calculated alpha': np.round(alphas_calculated, decimals=2),
    'calculate beta': np.round(betas_calculated, decimals=2)
})
df

con il risultato di

inserisci qui la descrizione dell'immagine

Ciò dimostra che i risultati della simulazione sono molto simili (se non uguali) a quelli dell'approccio analitico.

In breve, ho ancora bisogno di aiuto per capire cosa potrebbe essere sbagliato nei miei calcoli. Grazie. :)


3
Mi sembra che qualsiasi domanda che richieda ai lettori di superare 11 pagine di codice informatico, output statistico e algebra è improbabile che venga letta da nessuno, e tanto meno con una risposta convincente. Se sei interessato a perseguire questo, come sembri provenire dal tempo e dall'attenzione che ci hai dedicato, potrei suggerirti di identificare il nocciolo della questione e vedere se puoi spiegarlo e porre la tua domanda nello spazio di una o al massimo due pagine di materiale?
whuber

1
Ciao @whuber, grazie per il tuo suggerimento! La mia intenzione era quella di pubblicare dettagli (codice sorgente e spiegazioni) per consentire a chiunque di riprodurre i miei risultati, ma sembra che questa strategia non abbia funzionato molto bene come avete osservato correttamente :). Grazie ancora. Quindi ho modificato la domanda per riassumere il mio dubbio all'inizio del post. Spero che funzioni.
Francisco Fonseca,

Risposte:


3

Nel sito web del libro Computer Age Statistical Inference , c'è una sessione di discussione in cui Trevor Hastie e Brad Efron rispondono spesso a diverse domande. Quindi, ho postato questa domanda lì (come sotto) e ho ricevuto da Trevor Hastie la conferma che c'è un errore nel libro che verrà corretto (in altre parole, le mie simulazioni e calcoli - come implementato in Python in questa domanda - sono corretti ).

inserisci qui la descrizione dell'immagine

Quando Trevor Hastie rispose che "In effetti c = .75 per quella trama" significa che nella figura sottostante (Figura 2.2 originale del libro) il taglioc dovrebbe essere c=0.75 invece di c=0.4:

inserisci qui la descrizione dell'immagine

Così, usando le mie funzioni alpha_simulation(.), beta_simulation(.), alpha_calculation(.)e beta_calculation(.)(il cui codice completo Python è disponibile in questa domanda) ho ottenutoα=0.10 e β=0.38 per un taglio c=0.75 come conferma che il mio codice è corretto.

alpha_simulated_c075 = alpha_simulation(0.75, f0_density, f1_density, sample_size, replicates)
beta_simulated_c075 = beta_simulation(0.75, f0_density, f1_density, sample_size, replicates)

alpha_calculated_c075 = alpha_calculation(0.75, 0.0, 0.5, 1.0, sample_size)
beta_calculated_c075 = beta_calculation(0.75, 0.0, 0.5, 1.0, sample_size)

print("Simulated: c=0.75, alpha={0:.2f}, beta={1:.2f}".format(alpha_simulated_c075, beta_simulated_c075))
print("Calculated: c=0.75, alpha={0:.2f}, beta={1:.2f}".format(alpha_calculated_c075, beta_calculated_c075))

inserisci qui la descrizione dell'immagine

Alla fine, quando Trevor Hastie rispose che "... risultante in una soglia per x di .4" significa cheK=0.4nell'equazione seguente (vedere la sezione B di questa domanda):

X¯K, dove K=cσ2n(μ1-μ0)+(μ1+μ0)2

con il risultato di

tc(X)={1Se X¯K0Se X¯<K., dove K=cσ2n(μ1-μ0)+(μ1+μ0)2

Quindi, in Python possiamo ottenere K=0.4 per un taglio c=0.75 come sotto:

n = 10
m_0 = 0.0
m_1 = 0.5
variance = 1.0
c = 0.75

k = (c*variance)/(n*(m_1-m_0)) + (m_1+m_0)/2.0
threshold_for_x = k

print("threshold for x (when cutoff c=0.75) = {0:.1f}".format(threshold_for_x))

inserisci qui la descrizione dell'immagine

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.