如何从cv.glmnet交叉验证结果直接生成最优lambda对应的混淆矩阵
需求可实现性说明
你的需求完全可以实现,大部分人没注意到cv.glmnet有个默认关闭的keep参数,开启后就能直接拿到内置交叉验证过程的离群预测结果,完全没有数据泄露问题。
具体实现步骤
- 调用
cv.glmnet时显式设置keep = TRUE,如果要做留一交叉验证,把nfolds参数设置为样本总数即可。 - 调用完成后,返回对象的
fit.preval字段存储了所有交叉验证折、所有候选lambda对应的预测值,每一列对应一个lambda的结果,lambda字段存储了所有候选lambda的取值。 - 找到
lambda.min或lambda.1se对应的列索引,提取该列的预测值,就是每个样本在被划分为验证集时的预测结果,和真实标签对比即可直接生成混淆矩阵。
示例代码如下:
library(glmnet) # 示例数据:x为特征矩阵,y为二分类标签 x <- matrix(rnorm(100*20), 100, 20) y <- sample(0:1, 100, replace = TRUE) # 跑留一交叉验证的cv.glmnet,开启keep参数 cvfit <- cv.glmnet(x, y, family = "binomial", nfolds = nrow(x), keep = TRUE) # 提取lambda.min对应的预测概率 lambda_min_pos <- which(cvfit$lambda == cvfit$lambda.min) pred_prob <- cvfit$fit.preval[, lambda_min_pos] # 生成混淆矩阵 pred_label <- ifelse(pred_prob > 0.5, 1, 0) table(pred_label, y)
可选替代方案
如果场景有特殊需求不想用内置预测结果,可以用以下两种低耗时方案:
- 固定lambda搜索范围:先在全量数据集跑一次普通
glmnet得到完整的lambda序列,外层留一交叉验证每次循环直接用普通glmnet训练,复用预先生成的lambda序列,再用训练集指标选最优lambda,不需要每次循环都做内部交叉验证,耗时远低于常规嵌套交叉验证。 - 自定义折叠ID:自己生成留一交叉验证的
foldid参数传给cv.glmnet,可以保证交叉验证划分完全符合你的预期,得到的fit.preval结果和手动写循环的结果完全一致,还能保证和普通glm模型的交叉验证划分对齐,评估结果更具可比性。
内容的提问来源于stack exchange,提问作者BaileyA
相关产品推荐
相关产品推荐

