使用caret与roc()函数时的响应及预测参数选择疑问
关于逻辑回归交叉验证后ROC曲线差异的问题解答
你好呀!我来帮你拆解一下你遇到的问题——为什么你生成的两条ROC曲线不一样,以及roc()函数里的参数该怎么选。
先看你的代码,你用caret做了5折交叉验证的逻辑回归,然后用两种方式绘制ROC曲线,这两条曲线差异的核心原因,以及你操作里的问题,我给你一一梳理:
两条曲线差异的核心原因
这两条曲线完全不同,是因为你用了完全不匹配的数据和预测值类型:
- curve1:用的是原始全量训练集
mtcars$am作为真实标签,预测值是predict(m)——这是模型对整个训练集的类别预测结果。但这里的问题是:你用训练好的模型去预测训练集本身,得到的是训练集上的ROC,会严重高估模型的泛化性能,而且完全没用到交叉验证的结果。 - curve2:用的是交叉验证过程中保存的测试集真实标签
m$pred$obs,但预测值用的是m$pred$pred——这是交叉验证时模型对测试集的类别预测,不是概率值!ROC曲线的本质是基于不同阈值下的概率来计算灵敏度和特异度,用离散的类别预测的话,相当于只取了默认阈值(0.5)这一个点的结果,画出来的曲线自然不符合ROC的逻辑。
你操作里的两个关键错误
- 错误使用训练集预测评估性能:curve1用全训练集的真实标签和训练集预测结果画ROC,这不是交叉验证下的模型泛化能力评估,而是训练集上的过拟合表现,完全失去了交叉验证的意义。
- 用类别预测而非概率值作为predictor:ROC曲线需要连续的概率输出(比如模型预测为
one类的概率),而不是离散的one/zero类别。你用as.numeric(m$pred$pred)只是把类别转成了1/2这样的数值,没有利用概率信息,所以curve2的曲线是无效的。
正确的做法:用交叉验证的概率预测画ROC
要得到交叉验证下的真实ROC曲线,你需要用交叉验证中每个测试样本的真实标签和模型预测的正类概率:
# 正确提取交叉验证的真实标签和正类概率 # 注意:m$pred里的概率列名和你的正类一致,这里你的正类是'one',所以取one列 curve_correct <- roc( response = m$pred$obs, predictor = m$pred$one, # 用模型预测的正类概率,不是类别! plot = T, legacy.axes = T, percent = T, main = 'Cross-Validated ROC Curve', xlab = 'False Positive Percentage (1 - Specificity)', ylab = 'True Positive Percentage (Sensitivity)', print.auc = T, print.auc.x = 100, print.auc.y = 100, col = '#20B2AA', lwd = 4 )
补充:roc()参数的选择原则
response:必须是真实的二分类标签(因子或二分类变量),要和你模型训练时的标签保持一致。predictor:必须是模型预测的正类概率值(连续型变量),这样ROC才能遍历不同阈值,计算对应的灵敏度和特异度,这也是ROC曲线能评估模型整体性能的核心原因。如果用类别预测,就失去了ROC的意义。
另外,如果你只是想看看模型在训练集的表现(虽然不推荐用来评估泛化能力),也应该用predict(m, type = "prob")$one作为predictor,而不是类别预测值。
内容的提问来源于stack exchange,提问作者tibetish
相关产品推荐
相关产品推荐

