Mô phỏng phân tích công suất hồi quy logistic - thí nghiệm thiết kế


39

Câu hỏi này là để trả lời câu trả lời được đưa ra bởi @Greg Snow liên quan đến câu hỏi tôi đã hỏi liên quan đến phân tích sức mạnh với hồi quy logistic và SAS Proc GLMPOWER.

Nếu tôi đang thiết kế một thí nghiệm và sẽ phân tích kết quả theo hồi quy logistic giai thừa, làm thế nào tôi có thể sử dụng mô phỏng (và ở đây ) để tiến hành phân tích công suất?

Dưới đây là một ví dụ đơn giản trong đó có hai biến, biến đầu tiên có ba giá trị có thể {0,03, 0,06, 0,09} và biến thứ hai là chỉ báo giả {0,1}. Đối với mỗi chúng tôi ước tính tỷ lệ phản hồi cho từng kết hợp (# người trả lời / số người được tiếp thị). Hơn nữa, chúng tôi muốn có gấp 3 lần kết hợp các yếu tố đầu tiên so với các yếu tố khác (có thể được coi là bằng nhau) vì sự kết hợp đầu tiên này là phiên bản thử và đúng của chúng tôi. Đây là một thiết lập như được đưa ra trong khóa học SAS được đề cập trong câu hỏi được liên kết.

nhập mô tả hình ảnh ở đây

Mô hình sẽ được sử dụng để phân tích kết quả sẽ là hồi quy logistic, với các hiệu ứng và tương tác chính (phản hồi là 0 hoặc 1).

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

Làm cách nào tôi có thể mô phỏng một tập dữ liệu để sử dụng với mô hình này để tiến hành phân tích công suất?

Khi tôi chạy nó thông qua SAS Proc GLMPOWER(sử dụng STDDEV =0.05486016 tương ứng với sqrt(p(1-p))p là trung bình trọng số của tỷ lệ phản hồi được hiển thị):

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;

Lưu ý: GLMPOWERchỉ sử dụng các biến lớp (danh nghĩa) để 3, 6, 9 ở trên được coi là các ký tự và có thể là thấp, trung bình và cao hoặc bất kỳ ba chuỗi nào khác. Khi phân tích thực được tiến hành, Var1 sẽ được sử dụng một số (và chúng tôi sẽ bao gồm một thuật ngữ đa thức Var1 * Var1) để tính bất kỳ độ cong nào.

Đầu ra từ SAS là

nhập mô tả hình ảnh ở đây

Vì vậy, chúng tôi thấy rằng chúng tôi cần 762.112 làm cỡ mẫu của chúng tôi (hiệu ứng chính của Var2 là khó ước tính nhất) với công suất bằng 0,80 và alpha bằng 0,05. Chúng tôi sẽ phân bổ những thứ này sao cho số lần kết hợp cơ sở gấp 3 lần (tức là 0,375 * 762112) và phần còn lại chỉ rơi vào 5 kết hợp khác.


Điều này rất dễ thực hiện trong R. Câu hỏi thứ nhất: tôi có đúng không khi bạn muốn 75% tất cả các trường hợp là {var1 = .03, var2 = 0} & 25% cho tất cả các combo khác, và không có 3 đơn vị cho mỗi 1 đơn vị trong mỗi combo khác (nghĩa là 37,5%)? Câu hỏi thứ 2, bạn có thể chỉ định các hiệu ứng bạn quan tâm để phát hiện? Tức là, tỷ lệ cược đăng nhập là 1 so với 0 là bao nhiêu? Tỷ lệ cược thành công sẽ thay đổi như thế nào nếu var1 tăng 0,01? Bạn có nghĩ rằng có thể có một sự tương tác (nếu vậy, nó lớn như thế nào)? (NB, những câu hỏi Q này có thể khó trả lời, chiến lược 1 là chỉ định tỷ lệ 1 mà bạn nghĩ có thể có trong mỗi kết hợp.)
gung - Tái lập Monica

Thứ 1: Trọng số của 3 đối với trường hợp cơ sở là có gấp 3 lần số trường hợp trong đó {var1 = 0,03, var2 = 0}. Vì vậy, kết quả từ SAS (nói rằng chúng tôi cần 762.112 tổng kích thước mẫu để có 80% khả năng loại bỏ hiệu ứng chính var2 = 0, do đó, tổng kích thước mẫu chúng tôi cần) sẽ được phân bổ 37,5% cho trường hợp cơ sở này.
B_Miner

Thứ 2: Vâng tất cả những gì chúng tôi có là tỷ lệ phản hồi (là tỷ lệ dự kiến ​​của số lần thành công so với số lượng thử nghiệm). Vì vậy, nếu chúng tôi gửi 1.000 chữ cái với Var1 = 0,03 và Var2 = 0 có thể tương ứng với ưu đãi lãi suất trên phiếu mua hàng trực tiếp bằng thẻ tín dụng là 0,03 (3%) và không có nhãn dán trên phong bì (trong đó Var2 = 1 có nghĩa là có một nhãn dán), chúng tôi mong đợi 1000 * 0,0025 phản hồi.
B_Miner

Tiếp 2: Chúng tôi mong đợi một sự tương tác - do đó tỷ lệ phản hồi. Lưu ý rằng có một tốc độ phản hồi khác nhau cho Var2 = 0 tùy thuộc vào giá trị của Var1. Tôi không chắc làm thế nào để dịch những thứ này để ghi lại tỷ lệ cược và sau đó là một bộ dữ liệu mô phỏng.
B_Miner

Một điều cuối cùng, mặc dù. Tôi nhận thấy rằng tỷ lệ phản hồi là tuyến tính cho var1 khi var2 = 0 (nghĩa là, 25%, .30%, .35%). Bạn có ý định cho điều này là một hiệu ứng tuyến tính hoặc curvilinear? Bạn nên biết rằng xác suất có thể trông khá tuyến tính đối với các tập hợp con nhỏ trong phạm vi của chúng, nhưng thực tế không thể là tuyến tính. Hồi quy logistic là tuyến tính trong tỷ lệ cược log, không phải xác suất (tôi thảo luận về những thứ như thế trong câu trả lời của tôi ở đây ).
gung - Phục hồi Monica

Câu trả lời:


43

Sơ bộ:

  • NESα

    • Nα=.05
    • N
  • Ngoài bài đăng xuất sắc của @ GregSnow , một hướng dẫn thực sự tuyệt vời khác để phân tích sức mạnh dựa trên mô phỏng trên CV có thể được tìm thấy ở đây: Tính công suất thống kê . Để tóm tắt các ý tưởng cơ bản:

    1. Tìm ra hiệu ứng bạn muốn có thể phát hiện ra
    2. tạo dữ liệu N từ thế giới có thể
    3. chạy phân tích mà bạn dự định tiến hành trên những dữ liệu giả
    4. lưu trữ xem kết quả có 'đáng kể' theo alpha bạn đã chọn không
    5. BN
    6. N
  • ppBpB

  • Trong R, cách chính để tạo dữ liệu nhị phân với xác suất 'thành công' nhất định là ? Rbinom

    • Ví dụ: để có được số lần thành công trong số 10 thử nghiệm Bernoulli với xác suất p, mã sẽ là rbinom(n=10, size=1, prob=p)(bạn có thể muốn gán kết quả cho một biến để lưu trữ)
    • bạn cũng có thể tạo ra dữ liệu đó một cách thanh lịch bằng cách sử dụng ? runif , ví dụ:ifelse(runif(1)<=p, 1, 0)
    • nếu bạn tin rằng các kết quả được trung gian bởi một biến Gaussian tiềm ẩn, bạn có thể tạo biến tiềm ẩn dưới dạng hàm của các đồng biến của bạn với ? rnorm , sau đó chuyển đổi chúng thành xác suất pnorm()và sử dụng chúng trong rbinom()mã của bạn .
  • var12var1var2var12var2

  • Mặc dù được viết trong bối cảnh của một câu hỏi khác nhau, câu trả lời của tôi ở đây: Sự khác biệt giữa mô hình logit và probit có rất nhiều thông tin cơ bản về các loại mô hình này.
  • Cũng như có nhiều loại khác nhau của tỷ lệ lỗi loại I khi có nhiều giả thuyết (ví dụ, tỷ lệ lỗi mỗi Ngược lại , tỷ lệ lỗi familywise , & tỷ lệ lỗi mỗi gia đình ), vì vậy đang có các loại khác nhau của điện * (ví dụ, đối với một hiệu ứng được chỉ định trước , cho bất kỳ hiệu ứng nào , và cho tất cả các hiệu ứng ). Bạn cũng có thể tìm kiếm sức mạnh để phát hiện một sự kết hợp cụ thể của các hiệu ứng hoặc cho sức mạnh của một thử nghiệm đồng thời của toàn bộ mô hình. Tôi đoán từ mô tả của bạn về mã SAS của bạn là nó đang tìm kiếm cái sau. Tuy nhiên, từ mô tả của bạn về tình huống của bạn, tôi giả sử bạn muốn phát hiện các hiệu ứng tương tác ở mức tối thiểu.

  • Để biết cách suy nghĩ khác về các vấn đề liên quan đến quyền lực, hãy xem câu trả lời của tôi ở đây: Cách báo cáo độ chính xác chung trong việc ước tính tương quan trong bối cảnh chứng minh kích thước mẫu.

Sức mạnh hậu hoc đơn giản cho hồi quy logistic trong R:

Giả sử tỷ lệ phản hồi tích cực của bạn đại diện cho tình hình thực sự trên thế giới và bạn đã gửi 10.000 thư. Sức mạnh để phát hiện những hiệu ứng đó là gì? (Lưu ý rằng tôi nổi tiếng vì viết mã "không hiệu quả về mặt hài hước", những điều sau đây nhằm dễ theo dõi hơn là tối ưu hóa cho hiệu quả; thực tế, nó khá chậm.)

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

Vì vậy, chúng tôi thấy rằng 10.000 chữ cái không thực sự đạt được 80% năng lượng (dưới bất kỳ hình thức nào) để phát hiện các tỷ lệ phản hồi này. (Tôi không đủ chắc chắn về những gì mã SAS đang làm để có thể giải thích sự khác biệt rõ ràng giữa các cách tiếp cận này, nhưng mã này về mặt khái niệm rất đơn giản - nếu chậm - và tôi đã dành thời gian để kiểm tra nó, và tôi nghĩ rằng kết quả hợp lý.)

Sức mạnh a-tiên nghiệm dựa trên mô phỏng cho hồi quy logistic:

NNNN

NN

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

var12significant

N


Gung - WOW cảm ơn bạn rất nhiều vì một câu trả lời chi tiết và chu đáo như vậy! Khi tự viết và chơi với mã của bạn, các thuật ngữ bậc hai dường như là vấn đề - vì ít nhất 80% năng lượng đạt được với cỡ mẫu nhỏ hơn nhiều mà không xem xét nó trong mô hình.
B_Miner

1
Thật tuyệt, @B_Miner, đó là điều bạn muốn làm. Hơn nữa, đó là lý do tôi nghĩ rằng cách tiếp cận dựa trên mô phỏng là vượt trội so với phần mềm phân tích chỉ tạo ra một số (R cũng có cái này, pwrgói). Cách tiếp cận này mang đến cho bạn cơ hội để suy nghĩ rõ ràng hơn (& / hoặc tinh chỉnh suy nghĩ của bạn) về những gì bạn dự kiến ​​sẽ xảy ra, cách bạn giải quyết vấn đề đó, v.v. NB, tuy nhiên, bạn cần các thuật ngữ bậc hai, hoặc một cái gì đó tương tự, nếu tỷ lệ được đặt ra của bạn là đúng, thì chúng không phải là tuyến tính và chỉ riêng sự tương tác không cho phép bạn nắm bắt các mối quan hệ đường cong.
gung - Phục hồi Monica

Tôi nghĩ bạn nên thể hiện việc sử dụng polythay vì hiển thị cho người dùng mới của R chiến lược dễ bị lỗi hơn về các giá trị thô bình phương. Tôi nghĩ rằng mô hình đầy đủ nên được đặt ra như glm(responses~ poly(var1, 2) * var2, family=binomial(link="logit"). Nó sẽ ít bị lỗi thống kê trong giải thích và gọn hơn nhiều. Có thể không quan trọng trong trường hợp chính xác này khi bạn chỉ nhìn vào một sự phù hợp tổng thể, nhưng có thể dễ dàng đánh lừa những người dùng kém tinh tế, những người có thể bị cám dỗ để xem xét các thuật ngữ riêng lẻ.
DWin

@DWin, khi tôi sử dụng R để minh họa mọi thứ ở đây trên CV, tôi thực hiện nó theo cách không phải là R. Ý tưởng là phải minh bạch nhất có thể đối với những người không quen thuộc với W / R. Ví dụ, tôi không sử dụng các khả năng được vector hóa, đang sử dụng các vòng lặp =, v.v. Mọi người sẽ quen thuộc hơn với các biến bình phương từ hồi quy cơ bản lớp, và ít biết về những gì poly(), nếu họ không phải là người dùng R.
gung - Phục hồi Monica

17

Câu trả lời của @ Gung là tuyệt vời cho sự hiểu biết. Đây là cách tiếp cận mà tôi sẽ sử dụng:

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

Hàm này kiểm tra hiệu ứng tổng thể của v2, các mô hình có thể được thay đổi để xem xét các loại thử nghiệm khác. Tôi thích viết nó như là một hàm để khi tôi muốn kiểm tra một cái gì đó khác nhau, tôi có thể thay đổi các đối số của hàm. Bạn cũng có thể thêm một thanh tiến trình hoặc sử dụng gói song song để tăng tốc mọi thứ.

Ở đây tôi chỉ thực hiện 100 lần lặp lại, tôi thường bắt đầu ở mức đó để tìm kích thước mẫu gần đúng, sau đó tăng số lần lặp khi tôi ở trong công viên bóng phải (không cần lãng phí thời gian cho 10.000 lần lặp khi bạn có 20% năng lượng).


Cảm ơn Greg! Tôi đã tự hỏi về cách tiếp cận tương tự này (nếu tôi hiểu chính xác những gì bạn đã làm). Để xác nhận: Bạn có đang tạo một tập dữ liệu (có hiệu lực không, nhưng thực hiện với trọng số thay vì mạnh mẽ tạo các bản ghi riêng lẻ về các giá trị của Var1 và Var2 và sau đó là 1 và 0 cho phản hồi) rất lớn dựa trên "mydat" , phù hợp với hồi quy logistic và sau đó sử dụng các hệ số đó để lấy mẫu từ mô hình đề xuất trong mô phỏng? Có vẻ như đây là một cách chung để đưa ra các hệ số - sau đó nó giống như phản ứng của bạn về sức mạnh hồi quy thứ tự mà tôi liên kết đến.
B_Miner

Mô hình ban đầu sử dụng các trọng số để có được các hệ số sử dụng, nhưng trong mô phỏng nó đang tạo ra một khung dữ liệu với ncác hàng. Nó có thể hiệu quả hơn để làm trọng lượng trong chức năng là tốt.
Greg Snow

Tôi chính xác rằng bạn đang sử dụng dữ liệu ban đầu (làm cho nó lớn để có được ước tính rất tốt) cho mục đích nhận được các hệ số được sử dụng?
B_Miner

Vâng, lớn là để tỷ lệ nhân với trọng số cho một số nguyên.
Greg Snow

2
@B_Miner, tôi đang lên kế hoạch cho một bài viết, tôi không biết rằng có đủ cho một cuốn sách đầy đủ hay không. Nhưng cảm ơn vì sự khích lệ.
Greg Snow
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.