Reproduzieren Sie die Figur der "Computer Age Statistical Inference" von Efron und Hastie


8

Die zusammengefasste Version meiner Frage

(26. Dezember 2018)

Ich versuche, Abbildung 2.2 aus Computer Age Statistical Inference von Efron und Hastie zu reproduzieren , aber aus irgendeinem Grund, den ich nicht verstehen kann, stimmen die Zahlen nicht mit denen im Buch überein.

Angenommen, wir versuchen, zwischen zwei möglichen Wahrscheinlichkeitsdichtefunktionen für die beobachteten Daten , einer Nullhypothesendichte und einer alternativen Dichte . Eine Testregel besagt, welche Wahl, oder , wir treffen werden, wenn wir die Daten beobachtet haben . Jede solche Regel weist zwei häufig auftretende Fehlerwahrscheinlichkeiten auf: Auswahl von wenn tatsächlich generiert hat , und umgekehrt;xf0(x)f1(x)t(x)01xf1f0x

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

Sei das Wahrscheinlichkeitsverhältnis ,L(x)

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

Das Neyman-Pearson-Lemma besagt also, dass die der Form der optimale Algorithmus zum Testen von Hypothesen isttc(x)

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

Für und die Stichprobengröße wären die Werte für und für einen Cutoff ?f0N(0,1),f1N(0.5,1)n=10αβc=0.4

  • Aus Abbildung 2.2 der statistischen Inferenz des Computerzeitalters von Efron und Hastie haben wir:
    • α=0.10β = 0,38 c = 0,4 und für einen Cutoffβ=0.38c=0.4
  • Ich fand und für einen Cutoff Verwendung von zwei verschiedenen Ansätzen: A) Simulation und B) analytisch .α=0.15β=0.30c=0.4

Ich würde mich freuen, wenn mir jemand erklären könnte, wie man und für einen Cutoff erhält . Vielen Dank.α=0.10β=0.38c=0.4

Die zusammengefasste Version meiner Frage endet hier. Ab sofort finden Sie:

  • In Abschnitt A) Details und vollständiger Python-Code meines Simulationsansatzes .
  • In Abschnitt B) Details und vollständiger Python-Code des analytischen Ansatzes.

A) Mein Simulationsansatz mit vollständigem Python-Code und Erklärungen

(20. Dezember 2018)

Von dem Buch ...

In diesem Sinne bietet das Neyman-Pearson-Lemma einen optimalen Algorithmus zum Testen von Hypothesen. Dies ist vielleicht die eleganteste der frequentistischen Konstruktionen. In seiner einfachsten Formulierung geht das NP-Lemma davon aus, dass wir versuchen, zwischen zwei möglichen Wahrscheinlichkeitsdichtefunktionen für die beobachteten Daten , einer Nullhypothesendichte und einer alternativen Dichte . Eine Testregel besagt, welche Wahl, oder , wir treffen werden, wenn wir die Daten beobachtet haben . Jede solche Regel weist zwei häufig auftretende Fehlerwahrscheinlichkeiten auf: Auswahl von wenn tatsächlich generiert wirdxf0(x)f1(x)t(x)01xf1f0x und umgekehrt

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

Sei das Wahrscheinlichkeitsverhältnis , L.(x)

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

(Quelle: Efron, B. & Hastie, T. (2016). Statistische Inferenz des Computerzeitalters: Algorithmen, Evidenz und Datenwissenschaft. Cambridge: Cambridge University Press. )

Also habe ich den folgenden Python-Code implementiert ...

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

Wieder aus dem Buch ...

und definiere die durch tc(x)

tc(x)={1wenn log L.(x)c0wenn log L.(x)<c.

(Quelle: Efron, B. & Hastie, T. (2016). Statistische Inferenz des Computerzeitalters: Algorithmen, Evidenz und Datenwissenschaft. Cambridge: Cambridge University Press. )

Also habe ich den folgenden Python-Code implementiert ...

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

Zum Schluss aus dem Buch ...

Geben Sie hier die Bildbeschreibung ein

Wo man schließen kann, dass ein Cutoff und impliziert .c=0,4α=0,10β=0,38

Also habe ich den folgenden Python-Code implementiert ...

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)

und der Code ...

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

und der Code ...

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

um so etwas zu erhalten:

Geben Sie hier die Bildbeschreibung ein

das sieht ähnlich aus wie die ursprüngliche Figur aus dem Buch, aber die 3-Tupel aus meiner Simulation haben unterschiedliche Werte von und im Vergleich zu denen des Buches für denselben Cutoff . Zum Beispiel:(c,α,β)αβc

  • aus dem Buch, das wir haben(c=0,4,α=0,10,β=0,38)
  • Aus meiner Simulation haben wir:
    • (c=0,4,α=0,15,β=0,30)
    • (c=0,8,α=0,10,β=0,39)

Es scheint, dass der Cutoff aus meiner Simulation dem Cutoff aus dem Buch entspricht.c=0,8c=0,4

Ich würde mich freuen, wenn mir jemand erklären könnte, was ich hier falsch mache. Vielen Dank.

B) Mein Berechnungsansatz mit vollständigem Python-Code und Erklärungen

(26. Dezember 2018)

alpha_simulation(.), beta_simulation(.)Wir haben immer noch versucht, den Unterschied zwischen den Ergebnissen meiner Simulation ( ) und den im Buch vorgestellten zu verstehen. Mit Hilfe eines Freundes von mir (Sofia) haben wir und analytisch berechnet, anstatt über Simulation. .αβ

Einmal das

f0N.(0,1)
f1N.(0,5,1)

dann

f(x|μ,σ2)=ich=1n12πσ2e- -(xich- -μ)22σ2

Außerdem,

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

damit,

L.(x)=f1(x|μ1,σ2)f0(x|μ0,σ2)=ich=1n12πσ2e- -(xich- -μ1)22σ2ich=1n12πσ2e- -(xich- -μ0)22σ2

Wenn wir also einige algebraische Vereinfachungen durchführen (wie unten), haben wir:

L.(x)=(12πσ2)ne- -ich=1n(xich- -μ1)22σ2(12πσ2)ne- -ich=1n(xich- -μ0)22σ2

=e- -ich=1n(xich- -μ1)2+ich=1n(xich- -μ0)22σ2

=e- -ich=1n(xich2- -2xichμ1+μ12)+ich=1n(xich2- -2xichμ0+μ02)2σ2

=e- -ich=1nxich2+2μ1ich=1nxich- -ich=1nμ12+ich=1nxich2- -2μ0ich=1nxich+ich=1nμ022σ2

=e2(μ1- -μ0)ich=1nxich+n(μ02- -μ12)2σ2
.

Also, wenn

tc(x)={1wenn log L.(x)c0wenn log L.(x)<c.

dann haben wir für :Log L.(x)c

Log (e2(μ1- -μ0)ich=1nxich+n(μ02- -μ12)2σ2)c

2(μ1- -μ0)ich=1nxich+n(μ02- -μ12)2σ2c

ich=1nxich2cσ2- -n(μ02- -μ12)2(μ1- -μ0)

ich=1nxich2cσ22(μ1- -μ0)- -n(μ02- -μ12)2(μ1- -μ0)

ich=1nxichcσ2(μ1- -μ0)- -n(μ02- -μ12)2(μ1- -μ0)

ich=1nxichcσ2(μ1- -μ0)+n(μ12- -μ02)2(μ1- -μ0)

ich=1nxichcσ2(μ1- -μ0)+n(μ1- -μ0)(μ1+μ0)2(μ1- -μ0)

ich=1nxichcσ2(μ1- -μ0)+n(μ1+μ0)2

(1n)ich=1nxich(1n)(cσ2(μ1- -μ0)+n(μ1+μ0)2)

ich=1nxichncσ2n(μ1- -μ0)+(μ1+μ0)2

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

x¯k, wo k=cσ2n(μ1- -μ0)+(μ1+μ0)2

ergebend

tc(x)={1wenn x¯k0wenn x¯<k., wo k=cσ2n(μ1- -μ0)+(μ1+μ0)2

Um und zu berechnen , wissen wir, dass:αβ

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

damit,

α=Prf0{x¯k}},β=Prf1{x¯<k}}. wo k=cσ2n(μ1- -μ0)+(μ1+μ0)2

Für ...α

α=Prf0{x¯k}}=Prf0{x¯- -μ0k- -μ0}}

α=Prf0{x¯- -μ0σnk- -μ0σn}}

α=Prf0{Z-Scorek- -μ0σn}} wo k=cσ2n(μ1- -μ0)+(μ1+μ0)2

Also habe ich den folgenden Python-Code implementiert:

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)

Für ...β

β=Prf1{x¯<k}}=Prf1{x¯- -μ1<k- -μ1}}

β=Prf1{x¯- -μ1σn<k- -μ1σn}}

β=Prf1{Z-Score<k- -μ1σn}} wo k=cσ2n(μ1- -μ0)+(μ1+μ0)2

Daraus resultiert der folgende Python-Code:

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)

und der Code ...

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

und der Code ...

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

um eine Zahl und Werte für und zu erhalten, die meiner ersten Simulation sehr ähnlich sindαβ

Geben Sie hier die Bildbeschreibung ein

Und schließlich, um die Ergebnisse zwischen Simulation und Berechnung nebeneinander zu vergleichen ...

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

ergebend

Geben Sie hier die Bildbeschreibung ein

Dies zeigt, dass die Ergebnisse der Simulation denen des analytischen Ansatzes sehr ähnlich (wenn nicht sogar gleich) sind.

Kurz gesagt, ich brauche immer noch Hilfe, um herauszufinden, was in meinen Berechnungen falsch sein könnte. Vielen Dank. :) :)


3
Es scheint mir, dass jede Frage, bei der die Leser 11 Seiten Computercode, statistische Ausgabe und Algebra durchblättern müssen, von niemandem gelesen werden kann, geschweige denn mit Nachdruck beantwortet wird. Wenn Sie daran interessiert sind, dies zu verfolgen, wie Sie es anscheinend aus der Zeit und Aufmerksamkeit heraus tun, die Sie dafür aufgewendet haben, kann ich Ihnen vorschlagen, den Kern der Angelegenheit zu identifizieren und zu prüfen, ob Sie sie erklären und Ihre Frage im Rahmen von stellen können eine oder höchstens zwei Seiten Material?
whuber

1
Hallo @whuber, danke für deinen Vorschlag! Meine Absicht war es, Details (Quellcode und Erklärungen) zu veröffentlichen, damit jeder meine Ergebnisse reproduzieren kann, aber es scheint, dass diese Strategie nicht sehr gut funktioniert hat, wie Sie richtig beobachtet haben :). Danke nochmal. Dann habe ich die Frage bearbeitet, um meine Zweifel am Anfang des Beitrags zusammenzufassen. Ich hoffe das funktioniert.
Francisco Fonseca

Antworten:


3

Auf der Website des Buches Computer Age Statistical Inference gibt es eine Diskussionsrunde, in der Trevor Hastie und Brad Efron häufig auf mehrere Fragen antworten. Also habe ich diese Frage dort gepostet (siehe unten) und von Trevor Hastie die Bestätigung erhalten, dass es einen Fehler in dem Buch gibt, der behoben wird (mit anderen Worten, meine Simulationen und Berechnungen - wie in Python in dieser Frage implementiert - sind korrekt ).

Geben Sie hier die Bildbeschreibung ein

Wenn Trevor Hastie die geantwortet „Tatsächlich c = .75 für den plot“ bedeutet , dass zu der unteren Abbildung (ursprüngliche Bild 2.2 aus dem Buch) die Grenz sollte anstelle von :cc=0,75c=0,4

Geben Sie hier die Bildbeschreibung ein

Also, meine Funktionen alpha_simulation(.), beta_simulation(.), alpha_calculation(.)und beta_calculation(.)(das der volle Python - Code ist in dieser Frage zur Verfügung) Ich habe und für einen Cutoff als Bestätigung , dass mein Code korrekt ist.α=0,10β=0,38c=0,75

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

Geben Sie hier die Bildbeschreibung ein

Als Trevor Hastie schließlich antwortete, dass "... eine Schwelle für x von ergibt " , bedeutet dies, dass in der folgenden Gleichung (siehe Abschnitt B aus dieser Frage):k=0,4

x¯k, wo k=cσ2n(μ1- -μ0)+(μ1+μ0)2

ergebend

tc(x)={1wenn x¯k0wenn x¯<k., wo k=cσ2n(μ1- -μ0)+(μ1+μ0)2

In Python können wir also für einen Cutoff wie folgt erhalten:k=0,4c=0,75

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

Geben Sie hier die Bildbeschreibung ein

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.