Pengoptimal lme4 default membutuhkan banyak iterasi untuk data dimensi tinggi

12

TL; DR: lme4optimasi tampaknya linier dalam jumlah parameter model secara default, dan jauh lebih lambat daripada glmmodel yang setara dengan variabel dummy untuk grup. Apakah ada yang bisa saya lakukan untuk mempercepatnya?


Saya mencoba menyesuaikan model logit hierarkis yang cukup besar (~ baris 50k, 100 kolom, 50 grup). Memasukkan model logit normal ke data (dengan variabel dummy untuk grup) berfungsi dengan baik, tetapi model hierarkis tampaknya macet: fase optimisasi pertama selesai dengan baik, tetapi yang kedua melewati banyak iterasi tanpa perubahan apa pun dan tanpa berhenti .

EDIT: Saya menduga masalahnya terutama karena saya memiliki begitu banyak parameter, karena ketika saya mencoba mengatur maxfnke nilai yang lebih rendah itu memberikan peringatan:

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

Namun, perkiraan parameter tidak berubah sama sekali selama optimasi, jadi saya masih bingung tentang apa yang harus dilakukan. Ketika saya mencoba mengatur maxfnkontrol pengoptimal (meskipun ada peringatan), sepertinya hang setelah menyelesaikan optimasi.

Berikut beberapa kode yang mereproduksi masalah untuk data acak:

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)

Output ini:

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>

Saya mencoba pengaturan ncolke nilai-nilai lain, dan tampaknya jumlah iterasi yang dilakukan adalah (kurang-lebih) 40 per kolom. Jelas, ini menjadi sangat menyakitkan ketika saya menambahkan lebih banyak kolom. Apakah ada tweak yang bisa saya buat untuk algoritma optimasi yang akan mengurangi ketergantungan pada jumlah kolom?

Ben Kuhn
sumber
1
Akan sangat membantu untuk mengetahui model spesifik yang Anda coba cocokkan (terutama struktur efek acak).
Patrick S. Forscher
Sayangnya model yang tepat adalah milik. Ada satu tingkat efek acak, dengan ukuran grup berkisar antara ~ 100 dan 5000. Beri tahu saya jika saya dapat memberikan info relevan lainnya tentang model.
Ben Kuhn
OK, saya telah menambahkan beberapa kode yang mereproduksi masalah.
Ben Kuhn
1
Saya tidak punya jawaban lengkap untuk Anda, jadi saya akan meninggalkan ini sebagai komentar. Dalam pengalaman saya, glmerini sangat lambat, terutama untuk model yang memiliki struktur efek acak yang kompleks (misalnya, banyak lereng acak, efek acak silang, dll.). Saran pertama saya adalah untuk mencoba lagi dengan struktur efek acak yang disederhanakan. Namun, jika Anda mengalami masalah ini hanya dengan model intersepsi acak, masalah Anda mungkin hanya jumlah kasus, dalam hal ini Anda harus mencoba beberapa alat khusus untuk data besar.
Patrick S. Forscher
Ini memiliki masalah yang sama dengan 2 kelompok, bukan 50. Juga, pengujian dengan jumlah kolom yang lebih kecil, sepertinya jumlah iterasi kira-kira linier dalam jumlah kolom ... Apakah ada metode optimasi yang akan lebih baik di sini ?
Ben Kuhn

Jawaban:

12

Satu hal yang bisa Anda coba adalah mengubah pengoptimal. Lihat komentar Ben Bolker di masalah github ini . Implementasi nlopt dari bobyqa biasanya jauh lebih cepat daripada default (setidaknya setiap kali saya mencobanya).

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

Juga, lihat jawaban ini untuk lebih banyak opsi dan utas ini dari R-sig-mixed-models (yang terlihat lebih relevan dengan masalah Anda).

Sunting: Saya memberi Anda beberapa informasi kedaluwarsa terkait nloptr. Masuk lme4 1.1-7dan naik, nloptrsecara otomatis diimpor (lihat ?nloptwrap). Yang harus Anda lakukan adalah menambahkan

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

untuk panggilan Anda.

alexforrence
sumber
Terima kasih! Saya mencoba kode nlopt sekarang. Saya bertanya-tanya apakah ada sesuatu selain implementasi pengoptimal yang buruk yang terjadi, karena pemasangan glm dummified yang hampir setara jauh lebih cepat, tetapi saya akan melihat ...
Ben Kuhn
Nah, itu pasti lebih cepat, tetapi berhenti dengan kesalahan: PIRLS step-halvings failed to reduce deviance in pwrssUpdate. Apakah Anda tahu apa yang sedang terjadi di sini? Pesan kesalahannya tidak terlalu transparan ...
Ben Kuhn
Untuk tendangan, Anda dapat mencoba mengatur nAGQ = 0 (lihat utas yang saya tautkan untuk beberapa ide lagi). Saya tidak ingat apa yang menyebabkan kesalahan PIRLS, tetapi saya akan melihat-lihat.
alexforrence
Terima kasih banyak! Bisakah Anda mengarahkan saya ke sumber di mana saya bisa belajar lebih banyak tentang detail metode ini sehingga saya bisa menyelesaikan masalah seperti ini sendiri di masa depan? Optimasi terasa sangat seperti ilmu hitam bagi saya saat ini.
Ben Kuhn
2
nAGQ = 0 bekerja untuk saya pada contoh pengujian Anda dengan bobyqa default (berlari dalam ~ 15 detik), dan dalam 11 detik dengan nloptrbobyqa. Berikut adalah wawancara dengan John C. Nash (co-penulis optimdan optimxpaket) di mana ia melakukan penjelasan optimasi tingkat tinggi. Jika Anda mencari optimxatau nloptrmenggunakan CRAN, manual referensi masing-masing akan memberi tahu Anda lebih banyak tentang sintaks. nloptrjuga memiliki sketsa yang tersedia, yang melangkah sedikit lebih jauh ke dalam detail.
alexforrence