R语言中glm与bbmle包mle2拟合二项logit回归结果差异修正
问题原因排查
- 核心逻辑错误:负对数似然函数完全偏离优化目标
你在写负对数似然时错误将log=TRUE作为参数传给了sum()函数,这里存在两个层面的问题:sum()本身没有提供log形参,该参数不是函数的正式控制项,会被...参数捕获,当成逻辑值(等价于数值1)参与求和,完全无法实现“对概率取对数再求和”的需求。- 代码实际的计算逻辑是:先得到每个观测的伯努利概率值,再对这些概率值直接求和(额外加了2个来自错传参数的数值1),最后取负。这个目标函数和需要最大化的对数似然优化方向完全相反——优化器会为了最大化概率和,把预测概率p尽可能压到接近0的水平,最终收敛到参数空间的远端边界,导致你看到的极端系数估计、异常放大的标准误、所有p值接近1的结果。
- 冗余代码问题:你定义的
x1<-as.numeric(as.character(d$age))没有被任何函数引用,不影响结果但可以直接删除。 - 模型结构逻辑是正确的:线性预测子的截距项、ses为2的系数、ses为3的系数、sector为2的系数,这个设计和glm中因子变量的参照组设定是完全一致的,不需要调整。
修正方案
- 重写负对数似然的计算逻辑:单独计算每个观测的对数概率,求和后取负,和二项logit模型的定义完全对齐。
- 将初始值从0.0001调整为0,减少优化器的无效搜索,保证收敛到全局最大值。
修正后的可运行代码
# 数据读取与GLM拟合 d <- read.delim("http://dnett.github.io/S510/Disease.txt") d$disease <- factor(d$disease) d$ses <- factor(d$ses) d$sector <- factor(d$sector) glm2 <- glm(disease ~ ses + sector, family = binomial(link = logit), data = d) summary(glm2) # mle2拟合部分 y <- as.numeric(as.character(d$disease)) x2 <- as.numeric(as.character(d$sector)) x3 <- as.numeric(as.character(d$ses)) library(bbmle) # 修正后的负对数似然函数 nlldbin <- function(A, B, C, D){ eta <- A + B*(x3 == 2) + C*(x3 == 3) + D*(x2 == 2) p <- 1/(1 + exp(-eta)) # 逐观测计算对数似然,求和后取负 log_lik <- y*log(p) + (1-y)*log(1-p) -sum(log_lik, na.rm = TRUE) } st <- list(A = 0, B = 0, C = 0, D = 0) est_mle2 <- mle2(start = st, nlldbin, hessian = TRUE) summary(est_mle2)
结果一致性说明
运行修正后的代码后,mle2输出的系数估计、标准误、z统计量会和glm2的结果几乎完全一致——因为两种方法本质上都是在最大化同一个二项logit模型的对数似然函数,不存在模型设定层面的差异。
内容的提问来源于stack exchange,提问作者Jasmine Helen
相关产品推荐
相关产品推荐

