You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用nlme和自定义函数构建随机截距模型时遇错误

nlmer随机截距模型语法与收敛问题解决

1. 随机截距模型语法说明

你使用的1 | ID在lme4包的nlmer函数中是合法的线性模型随机截距语法,但在你的非线性模型场景下存在理解偏差:

  • 在非线性混合模型中,随机效应是针对你自定义的固定参数(如y0、x0B等)而非通用截距。你前三个模型都是指定x0B/y100B这些参数的随机变异,而1 | ID会试图给模型隐含的全局截距加随机效应,这与你自定义logistic函数中的y0参数(实际承担截距作用)产生冲突,导致模型无法识别,进而收敛失败。
  • 如果你想让logistic函数的截距(即y0)具有随机效应,正确的语法应该是(y0 | ID),而非(1 | ID)。

2. 报错原因分析

Error in fitted.model[[i]] : subscript out of bounds是因为循环逻辑存在漏洞:
当随机截距模型拟合失败(tol超过10仍未收敛)时,fitted.model[[i]]未被赋值,后续执行args.start <- fixef(fitted.model[[i]])时,因索引位置为空触发报错。

3. 解决方案

3.1 修正随机效应定义

将你代码中的label <- c(label, "1")替换为:

label <- c(label, "y0")

这样循环生成的随机效应部分会变为(y0 | ID),对应自定义logistic函数的截距随机变异,符合你的模型需求。

3.2 修复循环错误处理

修改循环中的拟合逻辑,避免空索引报错:

fitted.model <- list()
frm <- list()
frm.fixed <- "ptlt_logit ~ logistic.model (visibility, y0, y100B, dy100.F, a, x0B, dx0.F, isF_num)"
args.start <- c (y0 = y0,
                 y100B = y100,   dy100.F = 0,
                 a = a,
                 x0B = 0.30, dx0.F = 0)

for (i in seq (1, length (label))) {
  
  frm[[i]] <-  sprintf("%s ~ %s", frm.fixed,
                        paste (sapply (strsplit (label [i], "[.]") [[1]],
                                       function (x)
                                         sprintf("(%s|ID)", x),
                                       USE.NAMES = FALSE),
                               collapse = " + "))
  
  cat (sprintf("Model: %s\n", frm[[i]]))
  
  tol <- .0001
  current_model <- NULL
  while (TRUE) {
    if (tol > 10) {
      warning(sprintf("模型 %d 调整tol至%.4f后仍无法收敛", i, tol))
      break
    }
    tryCatch ({
      current_model <- nlmer (as.formula (frm[[i]]),
                              data = looking_times,
                              start = args.start,
                              control = nlmerControl (tolPwrss = tol, maxIter = 1000))
      break
    }, error = function (cond) {
      tol <<- 1.1 * tol
      cat (sprintf("Tolerance调整为: %.6f\n", tol))
    })
  }
  
  fitted.model[[i]] <- current_model
  # 仅当模型拟合成功时更新start参数
  if (!is.null(current_model)) {
    args.start <- fixef(current_model)
  } else {
    cat(sprintf("模型 %d 未拟合成功,保留原有初始参数\n", i))
  }
}

3.3 优化收敛策略

如果仍存在收敛问题,可尝试:

  • 更换优化器:添加optimizer = "bobyqa"至nlmerControl中,该优化器更适合非线性模型
  • 单独设置初始值:针对y0随机效应模型,手动设置更合理的y0初始值,而非沿用前一个模型的固定效应结果
  • 增大迭代次数:在nlmerControl中设置maxIter = 2000、maxEval = 2000

内容的提问来源于stack exchange,提问作者olowman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 00:34:56