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

mlr3中逻辑回归模型的残差计算方式探究

mlr3逻辑回归模型残差的底层计算逻辑及匹配问题

问题描述

使用mlr3包构建逻辑回归模型后,提取classifier_log_reg$model$residuals得到的残差,与手动计算的Pearson残差、Deviance残差均不匹配;且该残差与「实际值-预测值」的简单差值存在系统性关联,调整后呈现类Sigmoid关系,但用nls拟合标准Sigmoid曲线效果不佳。

复现代码

模型训练代码

library(mlr3)
library(tidyverse)

# 创建模拟数据
data <- data.frame(
  predictor = c(rnorm(50, mean = 0), rnorm(50, mean = 1)),
  dependant = as.factor(c(rep(0,50), rep(1, 50)))
)

# 定义并训练逻辑回归模型
classifier_log_reg <-  mlr_learners$get("classif.log_reg")
task <- mlr3::TaskClassif$new(id = "my_data",
                             backend = data,
                             target = "dependant", 
                             positive = "1")
classifier_log_reg$train(task, row_ids = 1:100)

手动计算残差的函数

pearson_residuals <- function(p, actual) {
  # 计算二项分布的标准差
  std_dev <- sqrt(p * (1 - p))
  
  # 避免除以0
  std_dev[std_dev == 0] <- .Machine$double.eps
  
  # Pearson残差
  residuals <- (actual - p) / std_dev
  
  return(residuals)
}

deviance_residuals <- function(p, actual) {
  # 避免log(0)
  p <- ifelse(p == 0, .Machine$double.eps, ifelse(p == 1, 1 - .Machine$double.eps, p))
  
  # Deviance残差
  residuals <- sign(actual - p) * sqrt(-2 * (actual * log(p) + (1 - actual) * log(1 - p)))
  
  return(residuals)
}

残差关联分析代码

# 从模型提取残差
residuals <- classifier_log_reg$model$residuals

# 手动计算实际值-预测值的差值
classifier_log_reg$predict_type <- 'prob'
predictions <- classifier_log_reg$predict(task, row_ids = 1:100)
predictions <- predictions$data$prob %>% as.data.frame() %>% pull(1) 
actual <- data$dependant %>% as.character() %>% as.numeric()
my_resid <-  actual - predictions 

# 调整后构建数据框并绘图
df <- data.frame(
  x = residuals - (actual * 2) + 1,
  y = (my_resid + 1) / 2,
  actual = actual
)

ggplot(df) + geom_point(aes(x = x, y = y))

Sigmoid拟合尝试代码

sigmoid <- function(x, L, k, x0) {
  L / (1 + exp(-k * (x - x0)))
}

model <- nls(y ~ sigmoid(x, L, k, x0), 
             data = df, 
             start = list(L = 1, k = 1,  x0 = 1),
             control = nls.control(maxiter = 100))

df$fitted <- predict(model, df)
ggplot(df) + geom_point(aes(x = fitted, y = y))

核心解答

1. mlr3逻辑回归残差的底层计算逻辑

mlr3的classif.log_reg学习器底层调用R基础包的glm()函数,使用binomial(link = "logit")族。你提取的classifier_log_reg$model$residuals是工作残差(Working Residuals),这是glm在迭代加权最小二乘拟合过程中使用的残差,计算公式为:
$$\text{Working Residuals} = \frac{y - \mu}{g'(\eta)}$$
其中:

  • $y$:实际响应值(0或1)
  • $\mu$:模型预测的事件发生概率(即你手动计算的predictions)
  • $\eta$:线性预测值(logit尺度,$\eta = \ln(\mu/(1-\mu))$)
  • $g'(\eta)$:logit链接函数的导数,即$g'(\eta) = \mu(1-\mu)$

代入后简化为:
$$\text{Working Residuals} = \frac{y - \mu}{\mu(1-\mu)}$$

2. 残差间的真实关系

你手动计算的my_resid = y - \mu,因此工作残差与my_resid的直接关系为:
$$\text{model_residuals} = \frac{\text{my_resid}}{\mu(1-\mu)}$$

你观察到的类Sigmoid关系,本质是因为$\mu$(预测概率)与自变量predictor本身遵循Sigmoid函数关系($\mu = 1/(1+e^{-(\beta_0 + \beta_1 \text{predictor})})$),经过你对x和y的变换后,间接呈现出类Sigmoid的关联,但这并非x与y直接的Sigmoid函数关系,因此用nls拟合标准Sigmoid曲线效果不佳。

3. 如何获取常见残差类型

如果需要获取Pearson残差或Deviance残差,可以直接对glm对象调用residuals()函数并指定类型:

# 获取Pearson残差
pearson_resid <- residuals(classifier_log_reg$model, type = "pearson")

# 获取Deviance残差
deviance_resid <- residuals(classifier_log_reg$model, type = "deviance")

# 获取响应残差(y - mu)
response_resid <- residuals(classifier_log_reg$model, type = "response")

这些结果会和你手动计算的对应残差值完全匹配。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 11:58:09