Reproduzca la figura de "Inferencia estadística de la era de la computadora" de Efron y Hastie


8

La versión resumida de mi pregunta.

(26 de diciembre de 2018)

Estoy tratando de reproducir la Figura 2.2 de la Inferencia estadística de la era de la computadora de Efron y Hastie, pero por alguna razón que no puedo entender, los números no se corresponden con los del libro.

Supongamos que estamos tratando de decidir entre dos posibles funciones de densidad de probabilidad para los datos observados , una densidad de hipótesis nula y una densidad alternativa . Una regla de prueba dice qué opción, oxf0(x)f1(x)t(x)01 , haremos con los datos observadosx. Cualquiera de estas reglas tiene dos probabilidades asociadas de error frecuentista: elegirf1 cuando en realidad f0 generado x, y viceversa,

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

Dejar L(x)ser la razón de verosimilitud ,

L(x)=f1(x)f0(x)

Entonces, el lema de Neyman-Pearson dice que la regla de prueba del formulario tc(x) es el algoritmo óptimo de prueba de hipótesis

tc(x)={1if log L(x)c0if log L(x)<c.

por f0N(0,1),f1N(0.5,1)y tamaño de muestra n=10 ¿Cuáles serían los valores para α y β para un corte c=0.4?

  • De la Figura 2.2 de la Inferencia estadística de la era de la computadora de Efron y Hastie tenemos:
    • α=0.10 y β=0.38 para un corte c=0.4
  • encontré α=0.15 y β=0.30 para un corte c=0.4utilizando dos enfoques diferentes: A) simulación y B) analíticamente .

Agradecería que alguien me explicara cómo obtener α=0.10 y β=0.38 para un corte c=0.4. Gracias.

La versión resumida de mi pregunta termina aquí. A partir de ahora encontrarás:

  • En la sección A) detalles y código completo de Python de mi enfoque de simulación .
  • En la sección B) detalles y código completo de Python del enfoque analítico .

A) Mi enfoque de simulación con código completo de Python y explicaciones

(20 de diciembre de 2018)

Del libro ...

En el mismo espíritu, el lema de Neyman-Pearson proporciona un algoritmo de prueba de hipótesis óptimo. Esta es quizás la más elegante de las construcciones frecuentistas. En su formulación más simple, el lema NP supone que estamos tratando de decidir entre dos posibles funciones de densidad de probabilidad para los datos observadosx, una densidad de hipótesis nula f0(x) y una densidad alternativa f1(x). Una regla de pruebat(x) dice qué opción, 0 o 1, haremos habiendo observado los datos x. Cualquiera de estas reglas tiene dos probabilidades asociadas de error frecuentista: elegirf1 cuando en realidad f0 generado x, y viceversa,

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

Dejar L(x)ser la razón de verosimilitud ,

L(x)=f1(x)f0(x)

(Fuente: Efron, B. y Hastie, T. (2016). Inferencia estadística de la era de la computadora: algoritmos, evidencia y ciencia de datos. Cambridge: Cambridge University Press. )

Entonces, implementé el código de Python a continuación ...

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))

De nuevo, del libro ...

y definir la regla de prueba tc(x) por

tc(x)={1if log L(x)c0if log L(x)<c.

(Fuente: Efron, B. y Hastie, T. (2016). Inferencia estadística de la era de la computadora: algoritmos, evidencia y ciencia de datos. Cambridge: Cambridge University Press. )

Entonces, implementé el código de Python a continuación ...

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, del libro ...

ingrese la descripción de la imagen aquí

Donde es posible concluir que un límite c=0.4 implicará α=0.10 y β=0.38.

Entonces, implementé el código de Python a continuación ...

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)

y el código ...

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_)

y el código ...

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-')

para obtener algo como esto:

ingrese la descripción de la imagen aquí

que se parece a la figura original del libro, pero las 3 tuplas (c,α,β) de mi simulación tiene diferentes valores de α y β cuando se compara con los del libro para el mismo límite c. Por ejemplo:

  • del libro que tenemos (c=0.4,α=0.10,β=0.38)
  • de mi simulación tenemos:
    • (c=0.4,α=0.15,β=0.30)
    • (c=0.8,α=0.10,β=0.39)

Parece que el límite c=0.8 de mi simulación es equivalente al corte c=0.4 del libro.

Agradecería que alguien me explicara qué estoy haciendo mal aquí. Gracias.

B) Mi enfoque de cálculo con código completo de Python y explicaciones

(26 de diciembre de 2018)

Aún tratando de entender la diferencia entre los resultados de mi simulación ( alpha_simulation(.), beta_simulation(.)) y los presentados en el libro, con la ayuda de un amigo estadístico (Sofía), calculamosα y β analíticamente en lugar de a través de la simulación, entonces ...

Una vez que

f0N(0,1)
f1N(0.5,1)

entonces

f(x|μ,σ2)=i=1n12πσ2e(xiμ)22σ2

Además,

L(x)=f1(x)f0(x)

entonces,

L(x)=f1(x|μ1,σ2)f0(x|μ0,σ2)=i=1n12πσ2e(xiμ1)22σ2i=1n12πσ2e(xiμ0)22σ2

Por lo tanto, al realizar algunas simplificaciones algebraicas (como se muestra a continuación), tendremos:

L(x)=(12πσ2)nei=1n(xiμ1)22σ2(12πσ2)nei=1n(xiμ0)22σ2

=ei=1n(xiμ1)2+i=1n(xiμ0)22σ2

=ei=1n(xi22xiμ1+μ12)+i=1n(xi22xiμ0+μ02)2σ2

=ei=1nxi2+2μ1i=1nxii=1nμ12+i=1nxi22μ0i=1nxi+i=1nμ022σ2

=e2(μ1μ0)i=1nxi+n(μ02μ12)2σ2
.

Así que si

tC(X)={1si log L(X)C0 0si log L(X)<C.

entonces para Iniciar sesión L(X)C tendremos:

Iniciar sesión (mi2(μ1-μ0 0)yo=1norteXyo+norte(μ0 02-μ12)2σ2)C

2(μ1-μ0 0)yo=1norteXyo+norte(μ0 02-μ12)2σ2C

yo=1norteXyo2Cσ2-norte(μ0 02-μ12)2(μ1-μ0 0)

yo=1norteXyo2Cσ22(μ1-μ0 0)-norte(μ0 02-μ12)2(μ1-μ0 0)

yo=1norteXyoCσ2(μ1-μ0 0)-norte(μ0 02-μ12)2(μ1-μ0 0)

yo=1norteXyoCσ2(μ1-μ0 0)+norte(μ12-μ0 02)2(μ1-μ0 0)

yo=1norteXyoCσ2(μ1-μ0 0)+norte(μ1-μ0 0)(μ1+μ0 0)2(μ1-μ0 0)

yo=1norteXyoCσ2(μ1-μ0 0)+norte(μ1+μ0 0)2

(1norte)yo=1norteXyo(1norte)(Cσ2(μ1-μ0 0)+norte(μ1+μ0 0)2)

yo=1norteXyonorteCσ2norte(μ1-μ0 0)+(μ1+μ0 0)2

X¯Cσ2norte(μ1-μ0 0)+(μ1+μ0 0)2

X¯k, dónde k=Cσ2norte(μ1-μ0 0)+(μ1+μ0 0)2

Resultando en

tC(X)={1Si X¯k0 0Si X¯<k., dónde k=Cσ2norte(μ1-μ0 0)+(μ1+μ0 0)2

Para calcular α y β, lo sabemos:

α=PrF0 0{t(X)=1},
β=PrF1{t(X)=0 0}.

entonces,

α=PrF0 0{X¯k},β=PrF1{X¯<k}. dónde k=Cσ2norte(μ1-μ0 0)+(μ1+μ0 0)2

por α ...

α=PrF0 0{X¯k}=PrF0 0{X¯-μ0 0k-μ0 0}

α=PrF0 0{X¯-μ0 0σnortek-μ0 0σnorte}

α=PrF0 0{puntaje zk-μ0 0σnorte} dónde k=Cσ2norte(μ1-μ0 0)+(μ1+μ0 0)2

Entonces, implementé el código de Python a continuación:

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)

por β ...

β=PrF1{X¯<k}=PrF1{X¯-μ1<k-μ1}

β=PrF1{X¯-μ1σnorte<k-μ1σnorte}

β=PrF1{puntaje z<k-μ1σnorte} dónde k=Cσ2norte(μ1-μ0 0)+(μ1+μ0 0)2

resultando en el código de python a continuación:

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)

y el código ...

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_)

y el código ...

# 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-')

para obtener una figura y valores para α y β muy similar a mi primera simulación

ingrese la descripción de la imagen aquí

Y finalmente para comparar los resultados entre simulación y cálculo lado a lado ...

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

Resultando en

ingrese la descripción de la imagen aquí

Esto muestra que los resultados de la simulación son muy similares (si no los mismos) a los del enfoque analítico.

En resumen, todavía necesito ayuda para descubrir qué podría estar mal en mis cálculos. Gracias. :)


3
Me parece que cualquier pregunta que requiera que los lectores recorran 11 páginas de código de computadora, resultados estadísticos y álgebra es poco probable que sea leída por nadie, y mucho menos respondida de manera convincente. Si está interesado en continuar con esto, como parece ser por el tiempo y la atención que ha dedicado a él, le sugiero que identifique el quid de la cuestión y vea si puede explicarlo y hacer su pregunta en el espacio de ¿una o como máximo dos páginas de material?
whuber

1
Hola @whuber, gracias por tu sugerencia! Mi intención era publicar detalles (código fuente y explicaciones) para permitir que cualquiera reproduzca mis resultados, pero parece que esta estrategia no funcionó muy bien como usted observó correctamente :). Gracias de nuevo. Luego edité la pregunta para resumir mi duda al comienzo de la publicación. Espero que esto funcione.
Francisco Fonseca

Respuestas:


3

En el sitio web del libro Computer Age Statistical Inference , hay una sesión de discusión donde Trevor Hastie y Brad Efron a menudo responden a varias preguntas. Entonces, publiqué esta pregunta allí (como a continuación) y recibí de Trevor Hastie la confirmación de que hay un error en el libro que se solucionará (en otras palabras, mis simulaciones y cálculos, tal como se implementaron en Python en esta pregunta) son correctos )

ingrese la descripción de la imagen aquí

Cuando Trevor Hastie respondió que "De hecho c = .75 para esa trama" significa que en la figura a continuación (Figura 2.2 original del libro) el límiteC debiera ser C=0,75 en vez de C=0.4 0.4:

ingrese la descripción de la imagen aquí

Por lo tanto, el uso de mis funciones alpha_simulation(.), beta_simulation(.), alpha_calculation(.)y beta_calculation(.)(cuyo código Python completa está disponible en esta pregunta) Tengoα=0,10 y β=0,38 para un corte C=0,75 como confirmación de que mi código es correcto.

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))

ingrese la descripción de la imagen aquí

Finalmente, cuando Trevor Hastie respondió que "... resultando en un umbral para x de .4" significa quek=0.4 0.4en la ecuación a continuación (ver sección B de esta pregunta):

X¯k, dónde k=Cσ2norte(μ1-μ0 0)+(μ1+μ0 0)2

Resultando en

tC(X)={1Si X¯k0 0Si X¯<k., dónde k=Cσ2norte(μ1-μ0 0)+(μ1+μ0 0)2

Entonces, en Python podemos obtener k=0.4 0.4 para un corte C=0,75 como a continuación:

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))

ingrese la descripción de la imagen aquí

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.