glmmTMB模型收敛状态程序化判定与状态码含义咨询
glmmTMB模型收敛状态判定与相关疑问
发现的4种收敛场景
- 正常收敛:无警告,
model$fit$convergence == 0,model$fit$message == "relative convergence (4)" - 收敛至奇异拟合:触发警告
model convergence problem; singular convergence (7),model$fit$convergence = 1,model$fit$message = "singular convergence (7)" - 疑似奇异拟合:触发警告
Model convergence problem; non-positive-definite Hessian matrix,但model$fit$convergence = 0,model$fit$message = "relative convergence (4)" - 伪收敛(不收敛):触发两条警告,分别为
Model convergence problem; non-positive-definite Hessian matrix.和Model convergence problem; false convergence (8),model$fit$convergence = 1,model$fit$message = "false convergence (8)"
核心问题
目前需要程序化检查收敛状态,但无法从拟合对象中直接提取警告信息,只能依赖model$fit$convergence和model$fit$message,但正常收敛(场景1)和疑似奇异拟合(场景3)的这两个输出完全一致,因此存在以下疑问:
- 如何从拟合对象中程序化明确判定所有收敛状态?
- 收敛消息/警告中括号内的数字(如4、7、8)代表什么?是否存在其他未发现的收敛状态?
解答
1. 程序化判定收敛状态的方法
glmmTMB的拟合对象中,除了model$fit里的基础信息,还可以通过两种方式明确区分所有收敛场景:
方法一:检查Hessian矩阵正定性
提取模型的Hessian矩阵并计算其特征值,若存在非正特征值,即可判定为场景3的疑似奇异拟合,结合model$fit$convergence == 0和model$fit$message == "relative convergence (4)",就能和场景1的正常收敛区分开:
library(glmmTMB) # 提取Hessian矩阵 hess <- getME(model, "hessian") # 计算特征值 eig_vals <- eigen(hess, only.values = TRUE)$values # 判断是否存在非正特征值 is_singular_hessian <- any(eig_vals <= 1e-8) # 用极小值替代0避免浮点误差
方法二:捕获拟合时的警告信息
在拟合模型时,通过withCallingHandlers()捕获所有警告内容,直接通过警告文本判定场景:
fit_warnings <- character(0) model <- withCallingHandlers( glmmTMB(y ~ x + (1 + x^2 | group), data = data), warning = function(w) { fit_warnings <<- c(fit_warnings, conditionMessage(w)) invokeRestart("muffleWarning") # 避免控制台输出警告 } ) # 根据警告内容判定场景 if (length(fit_warnings) == 0) { cat("场景1:正常收敛") } else if (any(grepl("singular convergence", fit_warnings))) { cat("场景2:收敛至奇异拟合") } else if (any(grepl("non-positive-definite Hessian matrix", fit_warnings)) && model$fit$convergence == 0) { cat("场景3:疑似奇异拟合") } else if (any(grepl("false convergence", fit_warnings))) { cat("场景4:伪收敛") }
2. 收敛状态数字的含义及其他状态
这些括号内的数字是nlopt优化库的收敛状态码,glmmTMB底层使用nlopt进行参数优化,常见状态码对应含义:
- 4:
NLOPT_SUCCESS_RELATIVE——相对收敛,目标函数的变化量小于设定的容差阈值 - 7:
NLOPT_FAILURE——优化失败,对应奇异收敛(通常是随机效应协方差矩阵接近奇异) - 8:
NLOPT_FAILURE的子类型,伪收敛,迭代过程未达到收敛标准就提前停止
除已发现的4种场景,实际使用中还可能遇到其他收敛状态,比如:
- 状态码1:
NLOPT_SUCCESS——绝对收敛,目标函数值达到预设的绝对容差 - 状态码5:
NLOPT_STOPVAL_REACHED——目标函数值达到预先设定的停止值 - 状态码6:
NLOPT_MAXEVAL_REACHED——达到最大迭代次数仍未收敛 - 状态码9:
NLOPT_INVALID_ARGS——输入参数无效(如模型公式错误、数据格式异常)
这些状态可通过nlopt的底层定义或glmmTMB的源码确认,遇到未知状态码时,可结合model$fit$message和优化过程的上下文判断具体原因。
各场景复现代码
library(glmmTMB) # 1. 正常收敛 set.seed(1) data <- data.frame(y = rnorm(100), x = rnorm(100), group = rep(1:10, each = 10)) model <- glmmTMB(y ~ x + (1 | group), data = data) model$fit$convergence # == 0 model$fit$message # "relative convergence (4)" # 2. 收敛至奇异拟合 set.seed(3) data <- data.frame(y = rnorm(100), x = rnorm(100), group = rep(1:10, each = 10)) model <- glmmTMB(y ~ x + (1 + x | group), data = data) model$fit$convergence # == 1 model$fit$message # "singular convergence (7)" # 3. 疑似奇异拟合 set.seed(5) data <- data.frame(y = rnorm(100), x = rnorm(100), group = rep(1:10, each = 10)) model <- glmmTMB(y ~ x + (1 + x^2 | group), data = data) model$fit$convergence # == 0 model$fit$message # "relative convergence (4)" # 4. 伪收敛(不收敛) set.seed(1) data <- data.frame(y = rnorm(100), x = rnorm(100), group = rep(1:10, each = 10)) data$y1 = data$y < -2 model <- glmmTMB(y1 ~ x + (1 + x | group), family = binomial, data = data) model$fit$convergence # == 1 model$fit$message # "false convergence (8)"
内容的提问来源于stack exchange,提问作者Robert Long
相关产品推荐
相关产品推荐

