デフォルトのlme4オプティマイザーでは、高次元のデータに対して多くの反復が必要です


12

TL; DR:lme4最適化は、デフォルトではモデルパラメータの数に直線的であるように思われる、とある遅く同等以上glmのグループのためのダミー変数を持つモデル。高速化するためにできることはありますか?


私はかなり大きな階層型ロジットモデル(〜5万行、100列、50グループ)に適合させようとしています。データへの通常のロジットモデルのフィッティング(グループのダミー変数を使用)は正常に機能しますが、階層モデルはスタックしているように見えます:最初の最適化フェーズは正常に完了しますが、2番目は何も変更せずに停止せずに多くの反復を実行します。

編集:私は問題が主に非常に多くのパラメータを持っていると疑っています、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
当てはめようとしている特定のモデル(特にランダム効果構造)を知っておくと役立ちます。
パトリックS.フォーシャー

残念ながら、正確なモデルは独自のものです。ランダム効果には1つのレベルがあり、グループサイズは100〜5000の範囲です。モデルに関するその他の関連情報を提供できるかどうか教えてください。
ベン・クーン

OK、問題を再現するコードを追加しました。
ベン・クーン

1
完全な回答はありませんので、コメントとして残しておきます。私の経験でglmerは、特に複雑なランダム効果構造(たとえば、多くのランダムな勾配、交差したランダム効果など)を持つモデルの場合、非常に遅くなります。私の最初の提案は、単純化されたランダム効果構造で再試行することです。ただし、ランダムインターセプトモデルのみでこの問題が発生している場合、問題は単にケースの数である可能性があります。その場合、ビッグデータ専用のツールを試す必要があります。
パトリックS.

50の代わりに2つのグループでも同じ問題があります。また、より少ない列数でテストすると、反復回数が列数でほぼ線形であるように見えます... ?
ベン・クーン

回答:


12

できることの1つは、オプティマイザーを変更することです。このgithub issueでBen Bolkerのコメントを参照してください。bobyqaのnlopt実装は通常、デフォルトよりもはるかに高速です(少なくとも試してみるたびに)。

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-7nloptr自動的にインポートされます(を参照?nloptwrap)。追加するだけです

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

あなたの呼び出しに。


ありがとうございました!私は今nloptコードを試しています。そこの場合、私は、ほぼ相当dummified GLMはそんなに速かったフィットするので、上に行く悪いオプティマイザの実装以外の何かを不思議を行いますが、私は参照してくださいよ...
ベンクーン

まあ、確かに高速でしたが、エラーで停止しました:PIRLS step-halvings failed to reduce deviance in pwrssUpdate。ここで何が起こっているのか考えていますか?エラーメッセージが...正確に透明ではない
ベンクーン

キックについては、nAGQ = 0に設定してみてください(リンク先のスレッドでいくつかのアイデアを参照してください)。PIRLSエラーの原因は覚えていませんが、見回します。
alexforrence

本当にありがとう!今後このような問題を自分で解決できるように、これらの方法の詳細について詳しく知ることができるリソースを教えていただけますか?最適化は、今のところ私にとって黒魔術のように感じます。
ベン・クーン

2
nAGQ = 0は、デフォルトのbobyqaを使用したテスト例(〜15秒で実行)、およびnloptrbobyqaを使用した11秒で機能しました。ここにありますジョン・C・ナッシュ(の共著者とのインタビューoptimoptimx、彼は、最適化の高レベルの説明を行うパッケージが)。あなたがルックアップする場合optimxnloptrCRAN上で、それぞれのリファレンスマニュアルでは、構文の詳細を教えてくれます。nloptrまた、ビネットも利用できます。これについては、もう少し詳しく説明します。
alexforrence
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.