เครื่องมือเพิ่มประสิทธิภาพ lme4 เริ่มต้นต้องการการวนซ้ำจำนวนมากสำหรับข้อมูลมิติสูง


12

TL; DR: lme4การเพิ่มประสิทธิภาพที่ดูเหมือนจะเป็นเชิงเส้นในจำนวนของพารามิเตอร์แบบโดยค่าเริ่มต้นและเป็นวิธีที่ช้ากว่าเทียบเท่าglmรุ่นด้วยตัวแปรดัมมี่สำหรับกลุ่ม มีอะไรที่ฉันสามารถทำได้เพื่อเร่งความเร็วหรือไม่


ฉันพยายามจัดวางโมเดล logit แบบลำดับชั้นที่ค่อนข้างใหญ่ (ประมาณ 50k แถว, 100 คอลัมน์, 50 กลุ่ม) การปรับโมเดล logit ปกติให้เข้ากับข้อมูล (ด้วยตัวแปรดัมมี่สำหรับกลุ่ม) ทำงานได้ดี แต่โมเดลลำดับชั้นดูเหมือนจะติดขัด: ขั้นตอนการปรับให้เหมาะสมครั้งแรกจะเสร็จสมบูรณ์ดี แต่ครั้งที่สองผ่านการทำซ้ำจำนวนมาก .

แก้ไข:ฉันสงสัยว่าปัญหาส่วนใหญ่คือฉันมีพารามิเตอร์มากมายเพราะเมื่อฉันพยายามตั้งค่าmaxfnที่ต่ำกว่าจะให้คำเตือน:

Warning message:
In commonArgs(par, fn, control, environment()) :
  maxfun < 10 * length(par)^2 is not recommended.

อย่างไรก็ตามการประมาณพารามิเตอร์ไม่ได้เปลี่ยนแปลงตลอดเวลาของการปรับให้เหมาะสมดังนั้นฉันยังคงสับสนเกี่ยวกับสิ่งที่ต้องทำ เมื่อฉันพยายามตั้งค่าmaxfnในตัวควบคุมเครื่องมือเพิ่มประสิทธิภาพ (แม้จะมีคำเตือน) ดูเหมือนว่าจะหยุดทำงานหลังจากการปรับให้เหมาะสมเสร็จแล้ว

นี่คือรหัสบางส่วนที่สร้างปัญหาให้กับข้อมูลสุ่ม:

library(lme4)

set.seed(1)

SIZE <- 50000
NGRP <- 50
NCOL <- 100

test.case <- data.frame(i=1:SIZE)
test.case[["grouping"]] <- sample(NGRP, size=SIZE, replace=TRUE, prob=1/(1:NGRP))
test.case[["y"]] <- sample(c(0, 1), size=SIZE, replace=TRUE, prob=c(0.05, 0.95))

test.formula = y ~ (1 | grouping)

for (i in 1:NCOL) {
    colname <- paste("col", i, sep="")
    test.case[[colname]] <- runif(SIZE)
    test.formula <- update.formula(test.formula, as.formula(paste(". ~ . +", colname)))
}

print(test.formula)

test.model <- glmer(test.formula, data=test.case, family='binomial', verbose=TRUE)

ผลลัพธ์นี้:

start par. =  1 fn =  19900.78 
At return
eval:  15 fn:      19769.402 par:  0.00000
(NM) 20: f = 19769.4 at           0     <other numbers>
(NM) 40: f = 19769.4 at           0     <other numbers>

ฉันพยายามตั้งค่าncolเป็นค่าอื่น ๆ และปรากฏว่าจำนวนการวนซ้ำที่ทำคือ (ประมาณ) 40 ต่อคอลัมน์ เห็นได้ชัดว่านี่กลายเป็นความเจ็บปวดครั้งใหญ่เมื่อฉันเพิ่มคอลัมน์อีก มีการปรับแต่งที่ฉันสามารถทำได้กับอัลกอริทึมการเพิ่มประสิทธิภาพที่จะลดการพึ่งพาจำนวนคอลัมน์หรือไม่?


1
การรู้โมเดลที่เฉพาะเจาะจงซึ่งคุณกำลังพยายามทำให้เป็นประโยชน์จะเป็นประโยชน์
Patrick S. Forscher

น่าเสียดายที่รุ่นที่แม่นยำนั้นเป็นกรรมสิทธิ์ มีเอฟเฟกต์สุ่มหนึ่งระดับโดยมีขนาดกลุ่มอยู่ระหว่าง ~ 100 ถึง 5,000 ให้ฉันรู้ว่าฉันสามารถให้ข้อมูลที่เกี่ยวข้องอื่น ๆ เกี่ยวกับแบบจำลองได้หรือไม่
Ben Kuhn

ตกลงฉันได้เพิ่มรหัสที่ทำให้เกิดปัญหาอีกครั้ง
Ben Kuhn

1
ฉันไม่มีคำตอบสำหรับคุณดังนั้นฉันจะทิ้งความคิดเห็นไว้ จากประสบการณ์ของฉันglmerค่อนข้างช้าโดยเฉพาะอย่างยิ่งสำหรับโมเดลที่มีโครงสร้างเอฟเฟกต์แบบสุ่มที่ซับซ้อน (เช่นลาดสุ่มจำนวนมากข้ามเอฟเฟกต์แบบสุ่ม ฯลฯ ) คำแนะนำแรกของฉันคือลองอีกครั้งด้วยโครงสร้างเอฟเฟกต์แบบสุ่มที่ง่ายขึ้น อย่างไรก็ตามหากคุณประสบปัญหานี้กับโมเดลการดักจับแบบสุ่มเท่านั้นปัญหาของคุณอาจเป็นจำนวนกรณีซึ่งในกรณีนี้คุณจะต้องลองใช้เครื่องมือบางอย่างสำหรับข้อมูลขนาดใหญ่โดยเฉพาะ
Patrick S. Forscher

มันมีปัญหาเดียวกันกับ 2 กลุ่มแทนที่จะเป็น 50 นอกจากนี้การทดสอบด้วยจำนวนคอลัมน์ที่น้อยกว่าดูเหมือนว่าจำนวนการวนซ้ำจะเป็นเส้นตรงในจำนวนคอลัมน์ ... มีวิธีการเพิ่มประสิทธิภาพที่จะทำได้ดีกว่าที่นี่หรือไม่ ?
Ben Kuhn

คำตอบ:


12

สิ่งหนึ่งที่คุณสามารถลองได้คือเปลี่ยนเครื่องมือเพิ่มประสิทธิภาพ ดูความคิดเห็นเบน Bolker ที่ปัญหา GitHub นี้ การปรับใช้ nlopt ของ bobyqa นั้นเร็วกว่าค่าเริ่มต้น (อย่างน้อยทุกครั้งที่ฉันลอง)

library(nloptr)
defaultControl <- list(algorithm="NLOPT_LN_BOBYQA",xtol_rel=1e-6,maxeval=1e5)
nloptwrap2 <- function(fn,par,lower,upper,control=list(),...) {
    for (n in names(defaultControl)) 
      if (is.null(control[[n]])) control[[n]] <- defaultControl[[n]]
    res <- nloptr(x0=par,eval_f=fn,lb=lower,ub=upper,opts=control,...)
    with(res,list(par=solution,
                  fval=objective,
                  feval=iterations,
                  conv=if (status>0) 0 else status,
                  message=message))
}

system.time(test.model <- glmer(test.formula, data=test.case, 
family='binomial', verbose=TRUE))

system.time(test.model2 <- update(test.model,
control=glmerControl(optimizer="nloptwrap2"))

ดูคำตอบนี้สำหรับตัวเลือกเพิ่มเติมและเธรดจาก R-sig-Mixed-models (ซึ่งมีความเกี่ยวข้องกับปัญหาของคุณมากกว่า)

แก้ไข: ฉันให้ข้อมูลล้าสมัยที่เกี่ยวข้องกับnloptrคุณ ในlme4 1.1-7ขึ้นไปnloptrจะถูกนำเข้าโดยอัตโนมัติ (ดู?nloptwrap) สิ่งที่คุณต้องทำคือเพิ่ม

control = [g]lmerControl(optimizer = "nloptwrap") # +g if fitting with glmer

เพื่อโทรของคุณ


ขอบคุณ! ฉันลองใช้รหัส nlopt ตอนนี้ ฉันสงสัยว่ามีบางอย่างนอกเหนือจากการใช้งานเครื่องมือเพิ่มประสิทธิภาพที่ไม่ดีเกิดขึ้นหรือไม่เนื่องจากการติดตั้ง glm ที่ทำให้เป็นรูปร่างที่เกือบจะเทียบเท่าได้เร็วขึ้นมาก แต่ฉันจะเห็น ...
Ben Kuhn

ดีมันก็แน่นอนเร็วขึ้น PIRLS step-halvings failed to reduce deviance in pwrssUpdateแต่มันหยุดที่มีข้อผิดพลาด: คุณมีความคิดใด ๆ ว่าเกิดอะไรขึ้นที่นี่ ข้อความแสดงข้อผิดพลาดนั้นไม่โปร่งใสเลย ...
เบ็นคุ

สำหรับการเตะคุณสามารถลองตั้งค่า nAGQ = 0 (ดูเธรดที่ฉันเชื่อมโยงสำหรับแนวคิดเพิ่มเติมอีกสองสามข้อ) ฉันจำไม่ได้ว่าอะไรเป็นสาเหตุของข้อผิดพลาดของ PIRLS แต่ฉันจะมองไปรอบ ๆ
alexforrence

ขอบคุณมาก! คุณช่วยชี้ให้ฉันเป็นแหล่งข้อมูลที่ฉันสามารถเรียนรู้เพิ่มเติมเกี่ยวกับรายละเอียดของวิธีการเหล่านี้เพื่อที่ฉันจะได้แก้ปัญหาเช่นนี้ได้ในอนาคต? การปรับให้เหมาะสมรู้สึกเหมือนเป็นเวทย์มนตร์ดำสำหรับฉันในขณะนี้
Ben Kuhn

2
nAGQ = 0 ทำงานให้ฉันในตัวอย่างทดสอบของคุณด้วยค่า bobyqa เริ่มต้น (ทำงานใน ~ 15 วินาที) และใน 11 วินาทีด้วยnloptrbobyqa ต่อไปนี้เป็นบทสัมภาษณ์ของ John C. Nash (ผู้เขียนร่วมoptimและoptimxแพ็คเกจ) ซึ่งเขาได้อธิบายถึงการเพิ่มประสิทธิภาพระดับสูง หากคุณค้นหาoptimxหรือnloptrCRAN คู่มืออ้างอิงของพวกเขาจะบอกคุณเพิ่มเติมเกี่ยวกับไวยากรณ์ nloptrยังมีบทความสั้น ๆ ซึ่งมีรายละเอียดเพิ่มเติมเล็กน้อย
alexforrence
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.