Мені було цікаво, чому саме збір даних до отримання значного результату (наприклад, ) (тобто p-хакерство) збільшує рівень помилок типу I?
Я також дуже вдячний за R
демонстрацію цього явища.
Мені було цікаво, чому саме збір даних до отримання значного результату (наприклад, ) (тобто p-хакерство) збільшує рівень помилок типу I?
Я також дуже вдячний за R
демонстрацію цього явища.
Відповіді:
Проблема полягає в тому, що ви даєте собі занадто багато шансів пройти тест. Це просто химерна версія цього діалогу:
Я переверну вас, щоб побачити, хто платить за вечерю.
Гаразд, я телефоную головам.
Щури, ти перемогла. Кращі два з трьох?
Щоб зрозуміти це краще, розгляньте спрощену, але реалістичну модель цієї послідовної процедури . Припустимо, ви почнете з "пробного запуску" певної кількості спостережень, але готові продовжити експерименти довше, щоб отримати значення р менше . Нульова гіпотеза полягає в тому, що кожне спостереження походить (незалежно) від стандартного нормального розподілу. Альтернативою є те, що надходять незалежно від нормального дисперсійного нормального розподілу з ненульовим середнім. Тестовою статистикою буде середнє значення всіх спостережень, , поділене на їх стандартну помилку, . Для двостороннього тесту критичними значеннями є значенняX i X i n ˉ X 1 / √ 0,0250,975Zα=±1,96 та процентних пунктів стандартного нормального розподілу, приблизно.
Це хороший тест - для одного експерименту з фіксованим розміром вибірки . Він має рівно ймовірність відкинути нульову гіпотезу, незалежно від того , що може бути.5 % n
Давайте алгебраїчно перетворимо це в еквівалентний тест на основі суми всіх значень,З п = Х 1 + Х 2 + ⋯ + Х п = п ˉ Х .
Таким чином, дані є "значущими", коли
це,
Якщо ми розумні, ми зменшимо свої втрати і відмовимось, коли зросте дуже великими, а дані все ще не ввійшли в критичну область.
Це описує випадкову ходу . Формула означає спорудження вигнутої параболічної «огорожі» або бар'єру навколо ділянки випадкової прогулянки : результат є «значущим», якщо якась точка випадкової прогулянки потрапляє на паркан.
Це властивість випадкових прогулянок, що якщо ми будемо чекати досить довго, дуже ймовірно, що в якийсь момент результат буде виглядати суттєвим.
Ось 20 незалежних моделювань до межі зразків. Усі вони починають тестування з проб, після чого ми перевіряємо, чи лежить кожна точка за межами бар'єрів, які були проведені за формулою . З моменту, коли статистичний тест спочатку є "значущим", імітовані дані пофарбовані в червоний колір.
Ви можете бачити, що відбувається: випадкова хода все більше і більше бігає вгору і вниз, коли росте. Шлагбауми розширюються приблизно однаковою швидкістю, але не досить швидко завжди, щоб уникнути випадкової прогулянки.
У 20% цих симуляцій було виявлено "суттєву" різницю - як правило, досить рано - хоча в кожному з них нульова гіпотеза абсолютно правильна! Запуск більшої кількості моделей такого типу свідчить про те, що справжній розмір тесту близький до а не передбачуване значення : тобто ваша готовність продовжувати шукати "значущість" до розміру вибірки дає шанс відхилити нуль, навіть якщо нуль є істинним.
Зауважте, що в усіх чотирьох "значущих" випадках, коли тестування тривало, дані перестали виглядати значущими в деяких точках. У реальному житті експериментатор, який рано зупиняється, втрачає шанс спостерігати такі "реверсії". Ця вибірковість завдяки необов'язковій зупинці змінює результати.
У послідовних тестах на чесність до доброти бар'єрами є лінії. Вони поширюються швидше, ніж тут показані зігнуті бар'єри.
library(data.table)
library(ggplot2)
alpha <- 0.05 # Test size
n.sim <- 20 # Number of simulated experiments
n.buffer <- 5e3 # Maximum experiment length
i.min <- 30 # Initial number of observations
#
# Generate data.
#
set.seed(17)
X <- data.table(
n = rep(0:n.buffer, n.sim),
Iteration = rep(1:n.sim, each=n.buffer+1),
X = rnorm((1+n.buffer)*n.sim)
)
#
# Perform the testing.
#
Z.alpha <- -qnorm(alpha/2)
X[, Z := Z.alpha * sqrt(n)]
X[, S := c(0, cumsum(X))[-(n.buffer+1)], by=Iteration]
X[, Trigger := abs(S) >= Z & n >= i.min]
X[, Significant := cumsum(Trigger) > 0, by=Iteration]
#
# Plot the results.
#
ggplot(X, aes(n, S, group=Iteration)) +
geom_path(aes(n,Z)) + geom_path(aes(n,-Z)) +
geom_point(aes(color=!Significant), size=1/2) +
facet_wrap(~ Iteration)
Люди, які не знайомі з тестуванням гіпотез, схильні вважати, що як тільки значення ап знизиться нижче .05, додавання більшої кількості учасників лише ще більше знизить значення р. Але це неправда. Згідно з нульовою гіпотезою, значення ap рівномірно розподіляється між 0 і 1 і може дуже відскакувати в цьому діапазоні.
Я імітував деякі дані в R (мої навички R досить базові). У цьому моделюванні я збираю 5 точок даних - кожен із випадково вибраним членством у групі (0 або 1) і кожен із випадково вибраним результатом вимірювання ~ N (0,1). Починаючи з учасника 6, я проводжу тест на кожній ітерації.
for (i in 6:150) {
df[i,1] = round(runif(1))
df[i,2] = rnorm(1)
p = t.test(df[ , 2] ~ df[ , 1], data = df)$p.value
df[i,3] = p
}
Значення р наведені на цьому малюнку. Зауважте, що я знаходжу значні результати, коли розмір вибірки становить приблизно 70-75. Якщо я зупинюсь на цьому, я в кінцевому підсумку вважаю, що мої висновки є вагомими, тому що я пропустив той факт, що мої значення p підскочили назад з більшою вибіркою (це насправді траплялося зі мною одного разу з реальними даними). Оскільки я знаю, що обидві групи населення мають середнє значення 0, це повинно бути помилковим позитивом. Це проблема з додаванням даних до p <.05. Якщо ви додасте проведення достатньої кількості тестів, p з часом переступить поріг .05, і ви зможете знайти значний вплив будь-якого набору даних.
R
код взагалі не працює.
df
спочатку (бажано в остаточному розмірі). Так як код починає писати в рядку 6 імплікації (що узгоджується з текстом відповіді) є те , що ДФ вже існує 5 рядків уже заповнене Може бути що - щось на зразок цього призначалися :. n150<-vector("numeric",150); df<-data.frame(gp=n150,val=n150,pval=n150); init<-1:5; df[init,1]<-c(0,1,0,1,0); df[init,2]<-rnorm(5)
( А потім запустити наведений вище код) , то , можливо: plot(df$pv[6:150])
Ця відповідь стосується лише ймовірності остаточного отримання «значного» результату та розподілу часу на цю подію за моделлю @ whuber.
Як і в моделі @whuber, нехай позначає значення тестової статистики після того , як зібрано спостережень, і припустимо, що спостереження є стандартними нормальними . Тоді такий, що поводиться як стандартний броунівський рух безперервного часу, якщо ми на даний момент ігноруємо той факт, що у нас процес дискретного часу (лівий сюжет внизу).
Нехай позначає перший час проходження через часові бар'єри (кількість спостережень, необхідних до того, як тест виявиться значним).
Розглянемо трансформований процес отриманий шляхом масштабування за його стандартним відхиленням в момент часу і, довівши нову шкалу часу таким, що З (1) і (2) випливає, що зазвичай розподіляється з і
Для перетвореної моделі бар'єри стають незалежними від часу константами, що дорівнює . Тоді відомо ( Nobile et al. 1985 ; Ricciardi & Sato, 1988 ), що перший час проходження процесу OU через ці бар'єри приблизно експоненціально розподілений з деяким параметром (залежно від бар'єрів у ) (оцінюється до для нижче). Також є додаткова маса точок розміром в . "Відхилення"в кінцевому підсумку відбувається з ймовірністю 1. Отже, (кількість спостережень, які необхідно зібрати, щоб отримати "значущий" результат) приблизно слідує за експоненціальним розподілом журналу з очікуваним значенням Таким чином, має кінцеве очікування, лише якщо (для достатньої кількості великий рівень значущості ).
Сказане ігнорує той факт, що для реальної моделі дискретний, а реальний процес - дискретний, а не безперервний час. Отже, вищезазначена модель завищує ймовірність того, що бар'єр був перекреслений (і недооцінює ), оскільки шлях вибірки безперервного часу може перетинати бар'єр лише тимчасово між двома сусідніми дискретними часовими точками і . Але такі події повинні мати незначну ймовірність для великих . E T t t + 1 t
На наступному малюнку показана оцінка Каплана-Мейєра за шкалою журналу журналу разом з кривою виживання для експоненціального наближення безперервного часу (червона лінія).
R код:
# Fig 1
par(mfrow=c(1,2),mar=c(4,4,.5,.5))
set.seed(16)
n <- 20
npoints <- n*100 + 1
t <- seq(1,n,len=npoints)
subset <- 1:n*100-99
deltat <- c(1,diff(t))
z <- qnorm(.975)
s <- cumsum(rnorm(npoints,sd=sqrt(deltat)))
plot(t,s,type="l",ylim=c(-1,1)*z*sqrt(n),ylab="S(t)",col="grey")
points(t[subset],s[subset],pch="+")
curve(sqrt(t)*z,xname="t",add=TRUE)
curve(-sqrt(t)*z,xname="t",add=TRUE)
tau <- log(t)
y <- s/sqrt(t)
plot(tau,y,type="l",ylim=c(-2.5,2.5),col="grey",xlab=expression(tau),ylab=expression(Y(tau)))
points(tau[subset],y[subset],pch="+")
abline(h=c(-z,z))
# Fig 2
nmax <- 1e+3
nsim <- 1e+5
alpha <- .05
t <- numeric(nsim)
n <- 1:nmax
for (i in 1:nsim) {
s <- cumsum(rnorm(nmax))
t[i] <- which(abs(s) > qnorm(1-alpha/2)*sqrt(n))[1]
}
delta <- ifelse(is.na(t),0,1)
t[delta==0] <- nmax + 1
library(survival)
par(mfrow=c(1,1),mar=c(4,4,.5,.5))
plot(survfit(Surv(t,delta)~1),log="xy",xlab="t",ylab="P(T>t)",conf.int=FALSE)
curve((1-alpha)*exp(-.125*(log(x))),add=TRUE,col="red",from=1,to=nmax)
Потрібно сказати, що вищезазначена дискусія стосується частістського світогляду, для якого множинність виходить з того, що ви даєте дані бути більш екстремальними, а не від шансів, що ви даєте ефект на існування. Першопричиною проблеми є те, що в p-значеннях та помилках I типу використовується кондиціонування потоку інформації в зворотному часі, завдяки чому важливо "як ти сюди потрапив" і що могло статися натомість. З іншого боку, байєсівська парадигма кодує скептицизм щодо впливу на сам параметр, а не на дані. Це робить кожну задню ймовірність інтерпретувати однаково, чи обчислювали ви іншу задню ймовірність ефекту 5 хвилин тому чи ні. Більш детальну інформацію та просте моделювання можна знайти на веб- сайті http://www.fharrell.com/2017/10/continuous-learning-from-data-no.
Ми вважаємо, що дослідник збирає зразок розміром , , щоб перевірити деяку гіпотезу . Він відкидає, якщо відповідна тестова статистика перевищує її рівень- критичне значення . Якщо цього немає, він збирає інший зразок розміром , і відхиляє, якщо тест відхиляє для комбінованого зразка . Якщо він все ще не отримує відхилення, він проходить таким чином, до разів усього.x 1 θ = θ 0 t α c n x 2 ( x 1 , x 2 ) K
Ця проблема, здається, вже була вирішена П. Армітажем, К. К. Макферсоном та Б. К. Роу (1969), журналом Королівського статистичного товариства. Серія A (132), 2, 235-244: "Неодноразові випробування значущості накопичувальних даних" .
Байєсівська точка зору на це питання, також обговорювана тут, до речі, обговорюється в Бергері та Вулперті (1988), "Принцип ймовірності" , Розділ 4.2.
Ось часткова реплікація результатів Armitage et al. (Код нижче), яка показує, як рівень значущості надувається при , а також можливі корекційні коефіцієнти для відновлення критичних значень рівня- . Зверніть увагу, що пошук сетки потребує деякого часу --- реалізація може виявитися досить неефективною.α
Розмір стандартного правила відхилення як функція від кількості спроб
Розмір як функція збільшення критичних значень для різних
Налаштовані критичні значення для відновлення 5% тестів як функції
reps <- 50000
K <- c(1:5, seq(10,50,5), seq(60,100,10)) # the number of attempts a researcher gives herself
alpha <- 0.05
cv <- qnorm(1-alpha/2)
grid.scale.cv <- cv*seq(1,1.5,by=.01) # scaled critical values over which we check rejection rates
max.g <- length(grid.scale.cv)
results <- matrix(NA, nrow = length(K), ncol=max.g)
for (kk in 1:length(K)){
g <- 1
dev <- 0
K.act <- K[kk]
while (dev > -0.01 & g <= max.g){
rej <- rep(NA,reps)
for (i in 1:reps){
k <- 1
accept <- 1
x <- rnorm(K.act)
while(k <= K.act & accept==1){
# each of our test statistics for "samples" of size n are N(0,1) under H0, so just scaling their sum by sqrt(k) gives another N(0,1) test statistic
rej[i] <- abs(1/sqrt(k)*sum(x[1:k])) > grid.scale.cv[g]
accept <- accept - rej[i]
k <- k+1
}
}
rej.rate <- mean(rej)
dev <- rej.rate-alpha
results[kk,g] <- rej.rate
g <- g+1
}
}
plot(K,results[,1], type="l")
matplot(grid.scale.cv,t(results), type="l")
abline(h=0.05)
cv.a <- data.frame(K,adjusted.cv=grid.scale.cv[apply(abs(results-alpha),1,which.min)])
plot(K,cv.a$adjusted.cv, type="l")