lme4に含まれるsleepstudyデータを検討してください。ベイツは、lme4に関する彼のオンラインブックでこれについて説明しています。第3章では、データの2つのモデルを検討します。
M0 :反応〜1 +日 +(1 | 件名)+(0+日| 件名)
そして
MA :反応〜1 + 日 + (日| 件名)
この研究には18人の被験者が参加し、10日間睡眠不足状態で研究しました。反応時間は、ベースラインとその後の日に計算されました。反応時間と睡眠不足の期間との間には明確な効果があります。被験者間にも大きな違いがあります。モデルAは、ランダムインターセプトとスロープ効果の間の相互作用の可能性を考慮します。たとえば、反応時間が悪い人は睡眠不足の影響により深刻に苦しむと想像してください。これは、ランダム効果に正の相関があることを意味します。
ベイツの例では、ラティスプロットから明らかな相関関係はなく、モデル間に有意差はありませんでした。しかし、上記の質問を調査するために、私は睡眠研究の適合値を取り、相関関係を調べ、2つのモデルのパフォーマンスを調べることにしました。
画像からわかるように、反応時間が長くなるとパフォーマンスが大幅に低下します。シミュレーションに使用された相関は0.58でした
私は人工データの適合値に基づいて、lme4のsimulateメソッドを使用して、1000個のサンプルをシミュレートしました。M0とMaをそれぞれに当てはめ、結果を調べました。元のデータセットには180の観測(18人の被験者ごとに10)があり、シミュレートされたデータは同じ構造を持ちます。
一番下の行は、ほとんど違いがないということです。
- 固定パラメーターは、両方のモデルでまったく同じ値を持ちます。
- ランダム効果はわずかに異なります。シミュレートされたサンプルごとに、18個の切片と18個の勾配ランダム効果があります。サンプルごとに、これらの効果は強制的に0に加算されます。つまり、2つのモデルの平均差は(人工的に)0です。しかし、分散と共分散は異なります。MAの下での共分散の中央値は104でしたが、M0では84でした(実際の値は112)。スロープとインターセプトの分散はMAよりM0で大きく、おそらく自由共分散パラメーターがない場合に必要な余地のあるゆらぎを得るためです。
- lmerのANOVAメソッドは、スロープモデルをランダムインターセプトのみのモデル(睡眠不足による影響なし)と比較するためのF統計量を提供します。明らかに、この値は両方のモデルの下で非常に大きかったが、通常は(常にではないが)MAの下で大きかった(平均62対平均55)。
- 固定効果の共分散と分散は異なります。
- 約半分の時間で、MAが正しいことがわかります。M0とMAを比較するためのp値の中央値は0.0442です。意味のある相関関係と180のバランスの取れた観測値が存在するにもかかわらず、正しいモデルは約半分の時間しか選択されません。
- 予測値は2つのモデルで異なりますが、わずかに異なります。予測間の平均差は0で、sdは2.7です。予測値自体のsdは60.9です
なぜこれが起こるのですか?@gungは、合理的に、相関の可能性を含めないと、ランダム効果が無相関になることを推測しました。おそらくそうすべきだ。ただし、この実装では、ランダム効果を相関させることができます。つまり、モデルに関係なく、データがパラメーターを正しい方向に引き出すことができます。間違ったモデルの誤りが尤度に現れるため、そのレベルで2つのモデルを(場合によっては)区別することができます。混合効果モデルは、基本的に各対象に線形回帰を当てはめており、モデルがどうあるべきかによって影響を受けます。間違ったモデルは、適切なモデルの下で得られるよりも妥当性の低い値の適合を強制します。しかし、パラメータは、一日の終わりに、実際のデータへの適合によって管理されます。
これが私のやや不格好なコードです。その考えは、睡眠研究データを適合させ、同じパラメーターを使用して、ランダム効果に対してより大きな相関関係を持つシミュレーションデータセットを構築することでした。そのデータセットはsimulate.lmer()に送られ、1000サンプルをシミュレートし、それぞれが両方向に適合しました。フィットしたオブジェクトをペアリングしたら、フィットのさまざまな機能を引き出して、t検定などを使用してそれらを比較できます。
# Fit a model to the sleep study data, allowing non-zero correlation
fm01 <- lmer(Reaction ~ 1 + Days +(1+Days|Subject), data=sleepstudy, REML=FALSE)
# Now use this to build a similar data set with a correlation = 0.9
# Here is the covariance function for the random effects
# The variances come from the sleep study. The covariance is chosen to give a larger correlation
sigma.Subjects <- matrix(c(565.5,122,122,32.68),2,2)
# Simulate 18 pairs of random effects
ranef.sim <- mvrnorm(18,mu=c(0,0),Sigma=sigma.Subjects)
# Pull out the pattern of days and subjects.
XXM <- model.frame(fm01)
n <- nrow(XXM) # Sample size
# Add an intercept to the model matrix.
XX.f <- cbind(rep(1,n),XXM[,2])
# Calculate the fixed effects, using the parameters from the sleep study.
yhat <- XX.f %*% fixef(fm01 )
# Simulate a random intercept for each subject
intercept.r <- rep(ranef.sim[,1], each=10)
# Now build the random slopes
slope.r <- XXM[,2]*rep(ranef.sim[,2],each=10)
# Add the slopes to the random intercepts and fixed effects
yhat2 <- yhat+intercept.r+slope.r
# And finally, add some noise, using the variance from the sleep study
y <- yhat2 + rnorm(n,mean=0,sd=sigma(fm01))
# Here is new "sleep study" data, with a stronger correlation.
new.data <- data.frame(Reaction=y,Days=XXM$Days,Subject=XXM$Subject)
# Fit the new data with its correct model
fm.sim <- lmer(Reaction ~ 1 + Days +(1+Days|Subject), data=new.data, REML=FALSE)
# Have a look at it
xyplot(Reaction ~ Days | Subject, data=new.data, layout=c(6,3), type=c("p","r"))
# Now simulate 1000 new data sets like new.data and fit each one
# using the right model and zero correlation model.
# For each simulation, output a list containing the fit from each and
# the ANOVA comparing them.
n.sim <- 1000
sim.data <- vector(mode="list",)
tempReaction <- simulate(fm.sim, nsim=n.sim)
tempdata <- model.frame(fm.sim)
for (i in 1:n.sim){
tempdata$Reaction <- tempReaction[,i]
output0 <- lmer(Reaction ~ 1 + Days +(1|Subject)+(0+Days|Subject), data = tempdata, REML=FALSE)
output1 <- lmer(Reaction ~ 1 + Days +(Days|Subject), data=tempdata, REML=FALSE)
temp <- anova(output0,output1)
pval <- temp$`Pr(>Chisq)`[2]
sim.data[[i]] <- list(model0=output0,modelA=output1, pvalue=pval)
}