Моделювання аналізу потужності логістичної регресії - розроблені експерименти


39

Це запитання є відповіддю на відповідь @Greg Snow щодо запитання, яке я задав щодо аналізу потужності з логістичною регресією та SAS Proc GLMPOWER.

Якщо я розробляю експеримент і аналізую результати факторної логістичної регресії, як я можу використовувати моделюваннятут ) для проведення аналізу потужності?

Ось простий приклад, коли є дві змінні, перша бере три можливі значення {0,03, 0,06, 0,09}, а друга - фіктивний показник {0,1}. Для кожного ми оцінюємо коефіцієнт відповіді для кожної комбінації (кількість респондентів / кількість людей, на яких продається). Крім того, ми хочемо мати втричі більше, ніж перші комбінації факторів, ніж інші (що можна вважати рівними), оскільки ця перша комбінація - наша випробувана і справжня версія. Це така установка, як наведена в курсі SAS, згаданому в пов'язаному питанні.

введіть тут опис зображення

Модель, яка буде використана для аналізу результатів, буде логістичною регресією з основними ефектами та взаємодією (відповідь - 0 або 1).

mod <- glm(response ~ Var1 + Var2 + I(Var1*Var2))

Як я можу імітувати набір даних, який використовуватиметься з цією моделлю для проведення аналізу потужності?

Коли я запускаю це через SAS Proc GLMPOWER(використовуючи STDDEV =0.05486016 який відповідає sqrt(p(1-p))де p - середньозважений показник показаних показників відповідей):

data exemplar;
  input Var1 $ Var2 $ response weight;
  datalines;
    3 0 0.0025  3
    3 1 0.00395 1
    6 0 0.003   1
    6 1 0.0042  1
    9 0 0.0035  1
    9 1 0.002   1;
run;

proc glmpower data=exemplar;
  weight weight;
  class Var1 Var2;
  model response = Var1 | Var2;
  power
    power=0.8
    ntotal=.
    stddev=0.05486016;
run;

Примітка: GLMPOWERвикористовуватимуться лише змінні класу (номінальні), тому 3, 6, 9 вище трактуються як символи і могли бути низькими, середніми та високими або будь-якими іншими трьома рядками. Коли буде проведений реальний аналіз, Var1 буде використаний числовий (і ми включимо поліномний термін Var1 * Var1) для обліку будь-якої кривизни.

Вихід від SAS є

введіть тут опис зображення

Отже, ми бачимо, що нам потрібно 762,112 як розмір вибірки (основний ефект Var2 найскладніше оцінити) з потужністю, що дорівнює 0,80, а альфа дорівнює 0,05. Ми виділимо їх так, щоб у 3 рази більше було базової комбінації (тобто 0,375 * 762112), а решта просто потрапляла однаково в інші 5 комбінацій.


Це легко зробити в Р. Перше запитання: чи правильно я вважаю, що ви хочете, щоб 75% всіх випадків були {var1 = .03, var2 = 0} & 25% для всіх інших комбо, а не 3 одиниці там на кожні 1 одиниця в кожному з інших комбо (тобто 37,5%)? 2-е питання, чи можете ви вказати ефекти, які вас цікавлять? Тобто, які були б коефіцієнти журналу 1 проти 0? Як повинні змінити шанси на успіх у журналі, якщо var1 подорожчає до .01? Як ви вважаєте, чи може бути взаємодія (якщо так, то наскільки вона велика)? (Зверніть увагу, на ці запитання важко відповісти. 1 стратегія полягає у визначенні пропорції 1, яку ви думаєте, що може бути в кожному комбо.)
gung - Відновіть Моніку

1-й: вага 3 для базового випадку полягає в тому, що в 3 рази більше випадків, коли {var1 = 0,03, var2 = 0}. Таким чином, результати SAS (який говорить про те, що нам потрібно 762,112 загального розміру вибірки, щоб мати 80% потужність відхилення основного ефекту var2 = 0, тобто загальний розмір вибірки, який нам потрібен) було б виділено 37,5% на цей базовий випадок.
B_Miner

Друге: Ну, все, що ми маємо, - це коефіцієнт відповіді (це очікуване відношення кількості успішності щодо кількості випробувань). Отже, якщо ми надішлемо 1000 листів з Var1 = 0,03 та Var2 = 0, які могли б відповідати пропонованій процентній ставці на пропозицію прямої пошти на кредитній картці 0,03 (3%) і на конверті немає наклейки (де Var2 = 1 означає, що є наклейка), ми очікуємо 1000 * 0,0025 відповідей.
B_Miner

Другий продовження: Ми очікуємо взаємодії - отже, швидкість відповідей. Зауважимо, що для Var2 = 0 різний коефіцієнт відповіді залежно від значення Var1. Я не впевнений, як перевести їх у журнал коефіцієнтів, а потім модельований набір даних.
B_Miner

Останнє, однак. Я помічаю, що коефіцієнт відповіді лінійний для var1, коли var2 = 0 (тобто .25%, .30%, .35%). Чи мали намір це зробити лінійним ефектом чи криволінійним? Ви повинні знати, що ймовірності можуть виглядати досить лінійно для малих підмножин їх діапазону, але насправді не можуть бути лінійними. Логістична регресія лінійна в рублених ладах, а не вірогідність (я обговорюю такі речі , як , що в моїй обороні тут ).
gung - Відновіть Моніку

Відповіді:


43

Попередні запитання:

  • Як було обговорено в посібнику G * Power , існує кілька різних типів аналізу потужності, залежно від того, що ви хочете вирішити. (Тобто , розмір ефекту , та потужність існують один щодо одного; вказівка ​​будь-яких трьох з них дозволить вирішити для четвертого.) E S αNESα

    • у вашому описі ви хочете знати відповідне для фіксації вказаних вами частот відповідей з та потужністю = 80%. Це апріорна сила . α = .05Nα=.05
    • ми можемо почати з потужних потужностей (визначити потужність, задану , швидкість реакції та альфа), оскільки це концептуально простіше, а потім рухатися вгоруN
  • Окрім відмінного поста @ GregSnow, тут можна знайти ще одне справді чудовий посібник із симуляційного аналізу потужностей на CV: Розрахунок статистичної потужності . Для узагальнення основних ідей:

    1. з'ясувати ефект, який потрібно виявити
    2. генерувати N даних із цього можливого світу
    3. запустіть аналіз, який ви маєте намір провести над цими підробленими даними
    4. зберігайте, чи є результати "значущими" відповідно до вибраної альфа
    5. повторіть багато ( ) разів і використовуйте% 'значущий' як оцінку (пост-hoc) потужності при цьомуНBN
    6. щоб визначити a priori потужність, шукайте можливі 's, щоб знайти значення, яке дає бажану потужність N
  • Чи знайдете ви значення для певної ітерації, можна зрозуміти як результат випробування Бернуллі з вірогідністю (де - сила). Пропорція, знайдена за ітераціями, дозволяє нам наблизити справжній . Для кращого наближення ми можемо збільшити , хоча це також змусить моделювання зайняти більше часу. p B p BppBpB

  • У R основним способом генерування двійкових даних із заданою ймовірністю «успіху» є «rbinom

    • Наприклад, щоб отримати кількість успіхів з 10 випробувань Бернуллі з вірогідністю р, код був би rbinom(n=10, size=1, prob=p)(ви, ймовірно, захочете призначити результат змінної для зберігання)
    • Ви також можете генерувати такі дані менш елегантно, використовуючи ? runif , наприклад,ifelse(runif(1)<=p, 1, 0)
    • якщо ви вважаєте, що результати опосередковуються латентною змінною Гаусса, ви можете генерувати приховану змінну як функцію ваших коваріатів з ? rnorm , а потім перетворювати їх у ймовірності з pnorm()та використовувати їх у своєму rbinom()коді.
  • Ви заявляєте, що "для включення будь-якої кривизни" ви будете включати поліноміальний термін Var1 * Var1). Тут панує плутанина; поліноміальні терміни можуть допомогти нам врахувати кривизну, але це термін взаємодії - це нам не допоможе. Тим не менш, ваш показник відповідей вимагає від нас включити як квадратичні терміни, так і умови взаємодії у нашу модель. Зокрема, ваша модель повинна включати: , та , за винятком основних термінів. v a r 1 v a r 2 v a r 1 2v a r 2var12var1var2var12var2

  • Незважаючи на те, що написано в контексті іншого питання, моя відповідь тут: Різниця між моделями logit і probit має багато основної інформації про ці типи моделей.
  • Так само , як існують різні види коефіцієнтів помилок типу I , коли є кілька гіпотез (наприклад, за відміну частоти помилок , коефіцієнт помилок familywise , і за сім'ю частоти помилок ), тому існують різні види харчування * (наприклад, для а один заздалегідь заданий ефект , для будь-якого ефекту та для всіх ефектів ). Ви також можете шукати потужність виявлення конкретної комбінації ефектів або потужність одночасного тестування моделі в цілому. З мого опису вашого коду SAS, я здогадуюсь, що він шукає останній. Однак, виходячи з опису вашої ситуації, я припускаю, що ви хочете виявити ефекти взаємодії як мінімум.

  • Щоб по-іншому подумати над питаннями, пов'язаними з владою, дивіться мою відповідь тут: Як повідомити загальну точність при оцінці кореляцій в контексті виправдання розміру вибірки.

Проста пост-хоч потужність для логістичної регресії в R:

Скажімо, ваш розміщений рівень відповідей відображає справжню ситуацію у світі, і що ви надіслали 10000 листів. Яка сила виявити ці наслідки? (Зауважте, що я відомий тим, що пишуть "комічно неефективний" код. Наступний проект призначений для легкого дотримання, а не оптимізований для ефективності; насправді це досить повільно.)

set.seed(1)

repetitions = 1000
N = 10000
n = N/8
var1  = c(   .03,    .03,    .03,    .03,    .06,    .06,    .09,   .09)
var2  = c(     0,      0,      0,      1,      0,      1,      0,     1)
rates = c(0.0025, 0.0025, 0.0025, 0.00395, 0.003, 0.0042, 0.0035, 0.002)

var1    = rep(var1, times=n)
var2    = rep(var2, times=n)
var12   = var1**2
var1x2  = var1 *var2
var12x2 = var12*var2

significant = matrix(nrow=repetitions, ncol=7)

startT = proc.time()[3]
for(i in 1:repetitions){
  responses          = rbinom(n=N, size=1, prob=rates)
  model              = glm(responses~var1+var2+var12+var1x2+var12x2, 
                           family=binomial(link="logit"))
  significant[i,1:5] = (summary(model)$coefficients[2:6,4]<.05)
  significant[i,6]   = sum(significant[i,1:5])
  modelDev           = model$null.deviance-model$deviance
  significant[i,7]   = (1-pchisq(modelDev, 5))<.05
}
endT = proc.time()[3]
endT-startT

sum(significant[,1])/repetitions      # pre-specified effect power for var1
[1] 0.042
sum(significant[,2])/repetitions      # pre-specified effect power for var2
[1] 0.017
sum(significant[,3])/repetitions      # pre-specified effect power for var12
[1] 0.035
sum(significant[,4])/repetitions      # pre-specified effect power for var1X2
[1] 0.019
sum(significant[,5])/repetitions      # pre-specified effect power for var12X2
[1] 0.022
sum(significant[,7])/repetitions      # power for likelihood ratio test of model
[1] 0.168
sum(significant[,6]==5)/repetitions   # all effects power
[1] 0.001
sum(significant[,6]>0)/repetitions    # any effect power
[1] 0.065
sum(significant[,4]&significant[,5])/repetitions   # power for interaction terms
[1] 0.017

Отже, ми бачимо, що 10 000 листів насправді не досягає 80% сили (будь-якого виду) для виявлення цих частот відповідей. (Я недостатньо впевнений, що робить код SAS, щоб можна було пояснити суттєву невідповідність між цими підходами, але цей код концептуально простий - якщо повільний - і я витратив деякий час на його перевірку, і я думаю, що це результати розумні.)

Апріорі потужність на основі симуляції для логістичної регресії:

Звідси ідея полягає в простому пошуку можливих , поки ми не знайдемо значення, яке дає бажаний рівень типу потужності, яка вас цікавить. Будь-яка стратегія пошуку, яку ви можете закодувати для роботи з цим, буде добре (в теорія). Враховуючи , які будуть потрібні для отримання таких невеликих ефектів, варто подумати над тим, як це зробити ефективніше. Мій типовий підхід - це просто груба сила, тобто оцінка кожної з яку я можу обґрунтовано вважати. (Однак зауважте, що я, як правило, вважаю лише невеликий діапазон, і я зазвичай працюю з дуже малими - принаймні порівняно з цим.) N N NNNNN

Натомість, моя стратегія тут полягала в тому, щоб закріпити можливі , щоб зрозуміти, яким буде коло повноважень. Таким чином, я вибрав в 500 000 і повторно запустив код (ініціюючи те ж насіння, для цього потрібно було півтори години). Ось результати: NNN

sum(significant[,1])/repetitions      # pre-specified effect power for var1
[1] 0.115
sum(significant[,2])/repetitions      # pre-specified effect power for var2
[1] 0.091
sum(significant[,3])/repetitions      # pre-specified effect power for var12
[1] 0.059
sum(significant[,4])/repetitions      # pre-specified effect power for var1X2
[1] 0.606
sum(significant[,5])/repetitions      # pre-specified effect power for var12X2
[1] 0.913
sum(significant[,7])/repetitions      # power for likelihood ratio test of model
[1] 1
sum(significant[,6]==5)/repetitions   # all effects power
[1] 0.005
sum(significant[,6]>0)/repetitions    # any effect power
[1] 0.96
sum(significant[,4]&significant[,5])/repetitions   # power for interaction terms
[1] 0.606

З цього ми бачимо, що величина ваших ефектів значно змінюється, і, отже, ваша здатність їх виявляти змінюється. Наприклад, ефект особливо важко виявити, він є лише 6% часу навіть за півмільйона літер. З іншого боку, модель в цілому завжди була значно кращою за нульову модель. Інші можливості є між ними. Хоча більшість «даних» викидаються на кожну ітерацію, все-таки можливе гарне вивчення. Наприклад, ми могли б використовувати матрицю для оцінки кореляції співвідношень ймовірностей різних змінних. var12significant

На закінчення мушу зазначити, що через складність та велику кількість пов'язаних із вашою ситуацією, це було не так просто, як я підозрював / стверджував у своєму первинному коментарі. Однак ви, звичайно, можете отримати уявлення про те, як це можна зробити в цілому, і питання, пов'язані з аналізом енергії, з того, що я тут виклав. HTH. N


Гунґ - ДЯКУ дуже дякую за таку детальну та продуману відповідь! Пишучи свій власний і граючи з вашим кодом, проблема, що стосується квадратичних термінів - як мінімум 80% потужності досягається значно меншим розміром вибірки, не враховуючи це в моделі.
B_Miner

1
Це чудово, @B_Miner, це те, що ти хочеш робити. Більше того, саме тому я вважаю, що підхід, заснований на моделюванні, перевершує аналітичне програмне забезпечення, яке просто випльовує число (R має це також pwrпакет). Такий підхід дає вам можливість набагато чіткіше (і / або вдосконалити своє мислення) про те, що ви очікуєте, що трапиться, як ви будете мати справу з тим, і т. Д. Примітка. Однак, вам потрібні квадратичні умови аналогічно, якщо розміщені вами ставки правильні, а / б вони не є лінійними, а сама взаємодія не дозволяє зафіксувати криволінійні відносини.
gung - Відновіть Моніку

Я думаю, ви повинні демонструвати використання, polyа не показувати новим користувачам R стратегію, більш схильну до помилок порівняння вихідних значень. Я думаю, що повна модель повинна була бути такою glm(responses~ poly(var1, 2) * var2, family=binomial(link="logit"). Це було б і менш схильне до статистичної помилки в інтерпретації, і набагато компактніше. Це може бути неважливим у цьому конкретному випадку, коли ви дивитесь лише на загальну форму, але легко може ввести в оману менш складних користувачів, які можуть спокуситись переглянути окремі умови.
DWin

@DWin, коли я використовую R, щоб проілюструвати речі тут на CV, я роблю це дуже не-R способом. Ідея полягає в тому, щоб бути максимально прозорим для тих, хто не знайомий з Р. Напр., Я не використовую векторизовані можливості, використовую петлі =тощо. Люди будуть більш знайомі з вирівнюванням змінних від базової регресії класу, і менше знають, що poly()таке, якщо вони не R користувачі.
gung - Відновіть Моніку

17

@ Відповідь Гунга чудово підходить для розуміння. Ось підхід, який я б застосував:

mydat <- data.frame( v1 = rep( c(3,6,9), each=2 ),
    v2 = rep( 0:1, 3 ), 
    resp=c(0.0025, 0.00395, 0.003, 0.0042, 0.0035, 0.002) )

fit0 <- glm( resp ~ poly(v1, 2, raw=TRUE)*v2, data=mydat,
    weight=rep(100000,6), family=binomial)
b0 <- coef(fit0)


simfunc <- function( beta=b0, n=10000 ) {
    w <- sample(1:6, n, replace=TRUE, prob=c(3, rep(1,5)))
    mydat2 <- mydat[w, 1:2]
    eta <- with(mydat2,  cbind( 1, v1, 
                v1^2, v2,
                v1*v2,
                v1^2*v2 ) %*% beta )
    p <- exp(eta)/(1+exp(eta))
    mydat2$resp <- rbinom(n, 1, p)

    fit1 <- glm( resp ~ poly(v1, 2)*v2, data=mydat2,
        family=binomial)
    fit2 <- update(fit1, .~ poly(v1,2) )
    anova(fit1,fit2, test='Chisq')[2,5]
}

out <- replicate(100, simfunc(b0, 10000))
mean( out <= 0.05 )
hist(out)
abline(v=0.05, col='lightgrey')

Ця функція перевіряє загальний ефект v2, моделі можна змінювати, щоб переглянути інші типи тестів. Мені подобається писати це як функцію, так що коли я хочу перевірити щось інше, я можу просто змінити аргументи функції. Ви також можете додати панель прогресу або використовувати паралельний пакет для прискорення роботи.

Тут я тільки зробив 100 реплікацій, я зазвичай починаю приблизно на цьому рівні, щоб знайти приблизний розмір вибірки, а потім ітерації, коли я знаходжусь у правильному парку кулі (не потрібно витрачати час на 10 000 ітерацій, коли у вас 20% потужності).


Дякую Грег! Мені було цікаво про цей самий підхід (якщо я правильно розумію, що ви зробили). Для підтвердження: чи створюєте ви набір даних (фактично, але ви робите це з вагами замість грубої сили, створюючи окремі записи значень Var1 та Var2, а потім 1 та 0 для відповіді), який дуже великий на основі "mydat" , що відповідає логістичній регресії, а потім використовувати ці коефіцієнти для вибірки із запропонованої моделі при моделюванні? Здається, це загальний спосіб придумати коефіцієнти - тоді це так само, як і ваша відповідь про силу порядкової регресії, з якою я пов'язаний.
B_Miner

Початкова модель використовує ваги для отримання коефіцієнтів для використання, але при моделюванні це створення кадру даних із nрядками. Може бути і ефективніше робити ваги в функції.
Грег Сног

Я правильний, що ви використовуєте дані спочатку (завдяки чому ви отримуєте дуже хороші оцінки) для отримання коефіцієнтів, які використовуються?
B_Miner

Так, добре, так що пропорція, менша від ваги, дає ціле число.
Грег Сног

2
@B_Miner, я планую статтю, я не знаю, достатньо для повної книги чи ні. Але дякую за заохочення.
Грег Сніг
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.