如何基于GLMNET逻辑回归的LOOCV样本外预测结果构建混淆矩阵并查看单个样本预测值
用LOOCV的glmnet获取样本外预测并生成混淆矩阵
嗨,我来帮你理清这个问题!你的思路完全正确,keep=TRUE确实是拿到LOOCV样本外预测结果的关键,不过我们可以更直观地提取每个样本的预测值,然后生成准确的混淆矩阵。
核心逻辑先明确
在LOOCV(留一交叉验证)中,每个样本都会被单独作为测试集,剩下的9个样本用来训练模型。cv.ridge$fit.preval这个矩阵就是存储了每个样本在被留作测试集时,针对所有lambda值的预测概率——它的维度是样本数 × lambda数量,每一行对应一个样本,每一列对应一个lambda值。
一步步实现你的需求
下面是修正后的完整代码,每一步都附带解释:
library(glmnet) library(dplyr) set.seed(123) x1 <- c(1, 2, 3, 4, 4, 5, 5, 6, 7, 8) x2 <- rnorm(10) y <- c(0, 0, 0, 0, 1, 0, 1, 1, 1, 1) df <- data.frame(x1, x2, y) # 带LOOCV的Ridge逻辑回归,keep=TRUE保留所有样本外预测结果 cv.ridge <- cv.glmnet(x=as.matrix(df[,-3]), y=y, alpha=0, family="binomial", nfolds=NROW(df), standardize = FALSE, keep = TRUE) plot(cv.ridge) cat("最优lambda值:", cv.ridge$lambda.min, "\n") cat("最优lambda对应的系数:\n") print(coef(cv.ridge, cv.ridge$lambda.min)) # 1. 提取最优lambda对应的样本外预测概率 best_idx <- which(cv.ridge$lambda == cv.ridge$lambda.min) # fit.preval的每一行就是对应样本的LOOCV预测概率 loocv_probs <- cv.ridge$fit.preval[, best_idx] # 2. 将概率转换为0/1预测类别(阈值设为0.5) loocv_preds <- ifelse(loocv_probs > 0.5, 1, 0) # 3. 查看每个样本的真实标签和样本外预测结果(这就是你要的10个样本各自的结果) sample_results <- data.frame(Observed = y, Predicted = loocv_preds, Probability = loocv_probs) print("每个样本的LOOCV样本外预测结果:") print(sample_results) # 4. 计算LOOCV的样本外分类准确率 loocv_ca <- mean(loocv_preds == y) cat("LOOCV样本外分类准确率:", loocv_ca, "\n") # 5. 生成LOOCV的样本外混淆矩阵 loocv_confusion <- table(Observed = y, Predicted = loocv_preds) print("LOOCV样本外混淆矩阵:") print(loocv_confusion)
解答你对原有代码的疑问
你最后用confusion.glmnet(cv.ridge$fit.preval, newy = y, family = "binomial")得到的cnf是一个列表,其中每个元素对应cv.glmnet中所有lambda值的混淆矩阵,所以print(cnf)会输出一堆结果。而best <- cv.ridge$index["min",]拿到的是lambda.min在lambda序列中的位置,cnf[[best]]确实是最优lambda下的混淆矩阵,和我们手动生成的loocv_confusion结果完全一致——只不过手动提取的方式更透明,能让你直接看到每个样本的预测细节。
内容的提问来源于stack exchange,提问作者odar
相关产品推荐
相关产品推荐

