修复 lme4 中的方差值
Fixing variance values in lme4
我正在使用 lme4
R 包使用 lmer()
函数创建线性混合模型。在这个模型中,我有四种随机效应和一种固定效应(截距)。我的问题是关于随机效应的估计方差。是否有可能以类似于在 SAS
中使用 PARMS
参数完成的方式为协方差参数指定初始值。
在以下示例中,估计方差为:
c(0.00000, 0.03716, 0.00000, 0.02306)
我想修复这些(例如)
c(0.09902947, 0.02460464, 0.05848691, 0.06093686)
所以估计没有。
> summary(mod1)
Linear mixed model fit by maximum likelihood ['lmerMod']
Formula: log_cumcover_mod ~ (1 | kildestationsnavn) + (1 | year) + (1 |
kildestationsnavn:year) + (1 | proevetager)
Data: res
AIC BIC logLik deviance df.resid
109.9 122.9 -48.9 97.9 59
Scaled residuals:
Min 1Q Median 3Q Max
-2.1056 -0.6831 0.2094 0.8204 1.7574
Random effects:
Groups Name Variance Std.Dev.
kildestationsnavn:year (Intercept) 0.00000 0.0000
kildestationsnavn (Intercept) 0.03716 0.1928
proevetager (Intercept) 0.00000 0.0000
year (Intercept) 0.02306 0.1518
Residual 0.23975 0.4896
Number of obs: 65, groups:
kildestationsnavn:year, 6; kildestationsnavn, 3; proevetager, 2; year, 2
Fixed effects:
Estimate Std. Error t value
(Intercept) 4.9379 0.1672 29.54
这是可能的,但有点老套。这是一个可重现的例子:
适合原始模型:
library(lme4)
set.seed(101)
ss <- sleepstudy[sample(nrow(sleepstudy),size=round(0.9*nrow(sleepstudy))),]
m1 <- lmer(Reaction~Days+(1|Subject)+(0+Days|Subject),ss)
fixef(m1)
## (Intercept) Days
## 251.55172 10.37874
恢复偏差(在本例中为 REML 标准)函数:
dd <- as.function(m1)
我要将标准偏差设置为零,以便我可以与之进行比较,即常规线性模型的系数。 (dd
的参数向量是包含模型中 scaled 随机效应项的列式、下三角、串联 Cholesky 因子的向量。幸运的是,如果所有你有 scalar/intercept-only 随机效应(例如 (1|x)
),然后这些对应于随机效应标准差,按模型标准差缩放)。
(ff <- dd(c(0,0))) ## new REML: 1704.708
environment(dd)$pp$beta(1) ## new parameters
## [1] 251.11920 10.56979
匹配项:
coef(lm(Reaction~Days,ss))
## (Intercept) Days
## 251.11920 10.56979
如果你想构造一个新的 merMod
对象,你可以按如下方式进行...
opt <- list(par=c(0,0),fval=ff,conv=0)
lmod <- lFormula(Reaction~Days+(1|Subject)+(0+Days|Subject),ss)
m1X <- mkMerMod(environment(dd), opt, lmod$reTrms, fr = lmod$fr,
mc = quote(hacked_lmer()))
现在假设我们要将方差设置为特定的非零值(比如 (700,30))。由于残差标准差的缩放,这会有点棘手...
newvar <- c(700,30)
ff2 <- dd(sqrt(newvar)/sigma(m1))
opt2 <- list(par=c(0,0),fval=ff,conv=0)
m2X <- mkMerMod(environment(dd), opt, lmod$reTrms, fr = lmod$fr,
mc = quote(hacked_lmer()))
VarCorr(m2X)
unlist(VarCorr(m2X))
## Subject Subject.1
## 710.89304 30.46684
所以这并没有让我们到达我们想要的地方(因为残差变化......)
buildMM <- function(theta) {
dd <- as.function(m1)
ff <- dd(theta)
opt <- list(par=c(0,0),fval=ff,conv=0)
mm <- mkMerMod(environment(dd), opt, lmod$reTrms, fr = lmod$fr,
mc = quote(hacked_lmer()))
return(mm)
}
objfun <- function(x,target=c(700,30)) {
mm <- buildMM(sqrt(x))
return(sum((unlist(VarCorr(mm))-target)^2))
}
s0 <- c(700,30)/sigma(m1)^2
opt <- optim(fn=objfun,par=s0)
mm_final <- buildMM(sqrt(opt$par))
summary(mm_final)
## Random effects:
## Groups Name Variance Std.Dev.
## Subject (Intercept) 700 26.458
## Subject.1 Days 30 5.477
## Residual 700 26.458
## Number of obs: 162, groups: Subject, 18
##
## Fixed effects:
## Estimate Std. Error t value
## (Intercept) 251.580 7.330 34.32
## Days 10.378 1.479 7.02
顺便说一句,当分组变量的数量非常少(例如 <5 或 6)水平时,通常不建议使用随机效应:参见 here ...
对于较大的数据集,可能值得注意的是 中的优化步骤可以简化为一维优化问题。最后的 theta
将始终是 c(700, 30)
.
的缩放器
特别是如果有更多 scalar/intercept-only 随机效果,则值得按以下方式更改 objfun
:
objfun <- function(x,target=c(700,30)) {
scaled_theta <- s0*x
mm <- buildMM(scaled_theta)
return(sum((unlist(VarCorr(mm))-target)^2))
}
s0 <- sqrt(c(700,30)/sigma(m1)^2)
opt <- optim(fn=objfun,par=1, method = "L-BFGS-B", lower = 0)
我正在使用 lme4
R 包使用 lmer()
函数创建线性混合模型。在这个模型中,我有四种随机效应和一种固定效应(截距)。我的问题是关于随机效应的估计方差。是否有可能以类似于在 SAS
中使用 PARMS
参数完成的方式为协方差参数指定初始值。
在以下示例中,估计方差为:
c(0.00000, 0.03716, 0.00000, 0.02306)
我想修复这些(例如)
c(0.09902947, 0.02460464, 0.05848691, 0.06093686)
所以估计没有。
> summary(mod1)
Linear mixed model fit by maximum likelihood ['lmerMod']
Formula: log_cumcover_mod ~ (1 | kildestationsnavn) + (1 | year) + (1 |
kildestationsnavn:year) + (1 | proevetager)
Data: res
AIC BIC logLik deviance df.resid
109.9 122.9 -48.9 97.9 59
Scaled residuals:
Min 1Q Median 3Q Max
-2.1056 -0.6831 0.2094 0.8204 1.7574
Random effects:
Groups Name Variance Std.Dev.
kildestationsnavn:year (Intercept) 0.00000 0.0000
kildestationsnavn (Intercept) 0.03716 0.1928
proevetager (Intercept) 0.00000 0.0000
year (Intercept) 0.02306 0.1518
Residual 0.23975 0.4896
Number of obs: 65, groups:
kildestationsnavn:year, 6; kildestationsnavn, 3; proevetager, 2; year, 2
Fixed effects:
Estimate Std. Error t value
(Intercept) 4.9379 0.1672 29.54
这是可能的,但有点老套。这是一个可重现的例子:
适合原始模型:
library(lme4)
set.seed(101)
ss <- sleepstudy[sample(nrow(sleepstudy),size=round(0.9*nrow(sleepstudy))),]
m1 <- lmer(Reaction~Days+(1|Subject)+(0+Days|Subject),ss)
fixef(m1)
## (Intercept) Days
## 251.55172 10.37874
恢复偏差(在本例中为 REML 标准)函数:
dd <- as.function(m1)
我要将标准偏差设置为零,以便我可以与之进行比较,即常规线性模型的系数。 (dd
的参数向量是包含模型中 scaled 随机效应项的列式、下三角、串联 Cholesky 因子的向量。幸运的是,如果所有你有 scalar/intercept-only 随机效应(例如 (1|x)
),然后这些对应于随机效应标准差,按模型标准差缩放)。
(ff <- dd(c(0,0))) ## new REML: 1704.708
environment(dd)$pp$beta(1) ## new parameters
## [1] 251.11920 10.56979
匹配项:
coef(lm(Reaction~Days,ss))
## (Intercept) Days
## 251.11920 10.56979
如果你想构造一个新的 merMod
对象,你可以按如下方式进行...
opt <- list(par=c(0,0),fval=ff,conv=0)
lmod <- lFormula(Reaction~Days+(1|Subject)+(0+Days|Subject),ss)
m1X <- mkMerMod(environment(dd), opt, lmod$reTrms, fr = lmod$fr,
mc = quote(hacked_lmer()))
现在假设我们要将方差设置为特定的非零值(比如 (700,30))。由于残差标准差的缩放,这会有点棘手...
newvar <- c(700,30)
ff2 <- dd(sqrt(newvar)/sigma(m1))
opt2 <- list(par=c(0,0),fval=ff,conv=0)
m2X <- mkMerMod(environment(dd), opt, lmod$reTrms, fr = lmod$fr,
mc = quote(hacked_lmer()))
VarCorr(m2X)
unlist(VarCorr(m2X))
## Subject Subject.1
## 710.89304 30.46684
所以这并没有让我们到达我们想要的地方(因为残差变化......)
buildMM <- function(theta) {
dd <- as.function(m1)
ff <- dd(theta)
opt <- list(par=c(0,0),fval=ff,conv=0)
mm <- mkMerMod(environment(dd), opt, lmod$reTrms, fr = lmod$fr,
mc = quote(hacked_lmer()))
return(mm)
}
objfun <- function(x,target=c(700,30)) {
mm <- buildMM(sqrt(x))
return(sum((unlist(VarCorr(mm))-target)^2))
}
s0 <- c(700,30)/sigma(m1)^2
opt <- optim(fn=objfun,par=s0)
mm_final <- buildMM(sqrt(opt$par))
summary(mm_final)
## Random effects:
## Groups Name Variance Std.Dev.
## Subject (Intercept) 700 26.458
## Subject.1 Days 30 5.477
## Residual 700 26.458
## Number of obs: 162, groups: Subject, 18
##
## Fixed effects:
## Estimate Std. Error t value
## (Intercept) 251.580 7.330 34.32
## Days 10.378 1.479 7.02
顺便说一句,当分组变量的数量非常少(例如 <5 或 6)水平时,通常不建议使用随机效应:参见 here ...
对于较大的数据集,可能值得注意的是 theta
将始终是 c(700, 30)
.
特别是如果有更多 scalar/intercept-only 随机效果,则值得按以下方式更改 objfun
:
objfun <- function(x,target=c(700,30)) {
scaled_theta <- s0*x
mm <- buildMM(scaled_theta)
return(sum((unlist(VarCorr(mm))-target)^2))
}
s0 <- sqrt(c(700,30)/sigma(m1)^2)
opt <- optim(fn=objfun,par=1, method = "L-BFGS-B", lower = 0)