在 lme4 中使用 cloglog 链接进行 PIRLS 步进减半

PIRLS step halving with cloglog link in lme4

提问人:Michael Roswell 提问时间:10/25/2023 更新时间:10/29/2023 访问量:50

问:

我收到 PIRLS 步进减半错误,使用 .在我看来,我生成的数据可能在下面模型过于复杂,这可能是完整的答案,但我对错误注释的理解不够好,无法自信。我看到了另一个答案,它引用了不太规范的链接函数的行为,并想知道机器中是否也存在导致此错误的问题。lme4::lmer()family = binomial(link = cloglog)

数据,使用 dput:

sub <- structure(list(sp = c("1", "1", "1", "1", "1", "2", "2", "2", 
                             "2", "2", "3", "3", "3", "3", "3", "4", "4", "4", "4", "4", "5", 
                             "5", "5", "5", "5"), rplct = c("X1", "X2", "X3", "X4", "X5", 
                                                            "X1", "X2", "X3", "X4", "X5", "X1", "X2", "X3", "X4", "X5", "X1", 
                                                            "X2", "X3", "X4", "X5", "X1", "X2", "X3", "X4", "X5"), abundance = c(131L, 
                                                                                                                                 124L, 128L, 114L, 108L, 62L, 57L, 62L, 65L, 54L, 45L, 45L, 35L, 
                                                                                                                                 38L, 33L, 29L, 31L, 30L, 32L, 30L, 21L, 20L, 25L, 23L, 28L), 
                      pres = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
                               1, 1, 1, 1, 1, 1, 1, 1, 1), tot_ab = c(288L, 277L, 280L, 
                                                                      272L, 253L, 288L, 277L, 280L, 272L, 253L, 288L, 277L, 280L, 
                                                                      272L, 253L, 288L, 277L, 280L, 272L, 253L, 288L, 277L, 280L, 
                                                                      272L, 253L)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
                                                                                                                                            -25L))

没有误差,拟合具有随机效应的模型,但没有偏移项:

no_off <- lme4::glmer(pres ~ (1|sp)
                       , family = binomial(link = cloglog)
                      , data = sub)

也没有偏移量,但没有随机效应:

no_re <- glm(pres ~ offset(log(tot_ab)) 
                             , family = binomial(link = cloglog)
                             , data = sub)

但 PIRLS 偏移和 RE 的减半误差

smaller <- lme4::glmer(pres ~ offset(log(tot_ab)) + (1|sp)
               , family = binomial(link = cloglog)
               , data = sub)

在此示例中,是什么导致了此错误?

我能够生成其他有趣且更可解析的错误,例如在模拟不适当的数据时,但不确定我的问题是什么。Error: cannot generate feasible simplex

谢谢!

优化 精度 LME4

评论

0赞 Ben Bolker 10/27/2023
我有点困惑,这似乎是不可复制的。(1) 我认为您的链接需要指定为字符串 ( ?(2) 您提供的数据子集只有一个响应值,这会引发“响应是常量”错误......这是大型数据集的子集吗?你能用它来生成一个可重复的数据集吗?(我认为问题源于逆链接函数的尾部极细,但使用可重现的示例进行调查会更容易......link = "cloglog")simulate()

答:

1赞 Ben Bolker 10/28/2023 #1

这个问题从根本上说是由 cloglog 反向链接函数的上尾细引起的,该函数与参数的默认起始值交互;默认情况下,固定效应系数设置为零,随机效应(缩放)方差默认设置为 1。这通常是有道理的,但这就是为什么当我们有一个大的偏移量和一个 cloglog 链接时它不起作用的原因:

cc <- make.link("cloglog")$linkinv
par(las=1, bty = "l")
curve(1-cc(x), from = -5, to = 10, log = "y", n= 501,
          ylab = "1-Prob(x)", xlab = "Linear predictor")

enter image description here

因此,线性预测变量的任何值大于约 3.6 时,将给出一个常数值。1-.Machine$double.eps

如果所有偏移量都明显高于 3.6(即总丰度大于约 = 36.6),则所有预测值都将位于上层“架子”上;此外,逆链接函数的梯度在此区域中也为零,尽管 R 将其设置为可能下溢的区域。exp(3.6).Machine$double.eps

目前尚不清楚为什么这会破坏PIRLS算法;它确实取决于导数(请参阅此处的等式 13,但此处描述的场景并没有明显打破这个等式。(权重矩阵中使用的逆方差会很大,但同样,这不一定是问题。1/.Machine$double.eps

library(lme4)
simfun <- function(seed = NULL) {
    if (!is.null(seed)) set.seed(seed)
    dd <- data.frame(sp = factor(rep(1:30, each = 5)),
                     tot_ab = rnbinom(150, mu = 250, size = 50))
    dd$pres <- suppressMessages(simulate(~ (1|sp) + offset(log(tot_ab))
                      , family = binomial(link = "cloglog")
                      , newdata = dd
                      , newparam = list(beta=-8, theta = 1))[[1]])
    dd
}

解决方案:使截距(本例中唯一的固定效应参数)的起始值小得多,使预测的起始值在更合理的范围内:

glmer(pres ~ (1|sp) + offset(log(tot_ab)),
      family = binomial(link = "cloglog"),
      data = dd,
      start = list(fixef = -log(min(dd$tot_ab))))

拟合有效(尽管我们确实收到一些收敛警告)。

定义自己的链接函数以不同方式设置下限和上限可能会起作用,但这可能会遇到其他数值问题......cloglog

另一种解决方案:与其使用总丰度的对数作为偏移量,不如使用 ;也就是说,不是对每个采样的个体生物体的发生概率进行建模,而是对最小样本大小的样本中发生的概率进行建模。(您还应该能够选择与最小样本数量相同数量级的整数。下面的代码演示了在对模拟数据进行的 1000 次运行中,拟合总是失败,但总是成功(尽管可能存在奇异拟合、收敛警告等),并且具有最小缩放偏移量。log(tot_ab)/min(tot_ab)offset(log(tot_ab))

fitfun <- function(dd, fix_offset = FALSE) {
    if (!fix_offset) {
        form <- pres ~ (1|sp) + offset(log(tot_ab))
    } else {
        form <- pres ~ (1|sp) + offset(log(tot_ab)/min(tot_ab))
    }
    res <- try(
        suppressMessages(
            glmer(
                form
              , family = binomial(link = "cloglog")
              , data = dd)), silent = TRUE
    )
    if (!inherits(res, "try-error")) return("OK")
    as.character(res)
}

适合原始偏移量:

set.seed(101)
res <- replicate(1000, fitfun(simfun()))
table(res)
Error : (maxstephalfit) PIRLS step-halvings failed to reduce deviance in pwrssUpdate
                                                                                     8 
                                            Error : cannot generate feasible simplex
                                                                                   983 
                          Error : pwrssUpdate did not converge in (maxit) iterations

                                                                                     9 

现在拟合最小缩放偏移量:

res <- replicate(1000, fitfun(simfun(), fix_offset = TRUE))
table(res)
res
  OK 
1000 

评论

0赞 Michael Roswell 10/29/2023
感谢@BenBolker编写了一个干净的模拟,提供了最初的重新缩放偏移建议,以及这个改进的答案,它清楚地勾勒了问题,并提供了一个看似更通用的解决方案,以帮助确保可接受的起始固定效应参数值!
0赞 Michael Roswell 10/29/2023
我用一些数据玩过这个,重新缩放的偏移还没有失败,但已经失败了几次。还没有一个最小的可重复的例子,但会在准备好后发布。start=list(fixef = -log(min(dd$totab)))