R中惩罚逻辑回归混淆矩阵报错及F1等指标计算求助
问题排查与解决
confusionMatrix报错原因
第一个报错the data and reference factors must have the same number of levels:本质是预测值(pred)和测试集真实因变量的因子水平不匹配——要么一方是因子另一方不是,要么两者的水平数量、标签不一致。比如测试集因变量是二元因子,但预测值只有单一类别(比如全是“未失败”),就会触发这个错误。
第二个报错the data cannot have more levels than the reference:说明预测值的因子水平比真实值还多。比如真实值只有“失败”“未失败”两个水平,但预测值里出现了第三个不存在的水平,或者转因子时没指定固定水平,导致额外生成了水平。
解决步骤
- 先统一所有因变量的因子格式
把训练集、测试集的因变量都转成相同水平顺序的因子,避免标签或顺序不一致:# 自定义水平和标签,确保训练/测试集一致 train$`Fail (1=yes)` <- factor(train$`Fail (1=yes)`, levels = c("0", "1"), labels = c("未失败", "失败")) test$`Fail (1=yes)` <- factor(test$`Fail (1=yes)`, levels = c("0", "1"), labels = c("未失败", "失败")) - 强制预测值匹配真实值的水平
模型预测后,把预测结果转成和测试集因变量完全一致的因子:# 以glmnet为例,先得到类别预测结果 pred <- predict(model, newdata = test, type = "class") # 强制对齐真实值的因子水平 pred <- factor(pred, levels = levels(test$`Fail (1=yes)`)) - 检查水平分布
用table(pred)和table(test$Fail (1=yes))查看两者的类别分布。如果预测值只有一个水平(比如测试集7个样本里模型全预测成同一类),这时候confusionMatrix会报错——因为二元分类要求两个水平,这种情况是样本量太小导致的(n=32确实太小,测试集仅7行很容易出现极端情况)。
手动计算精确率、召回率、F-score
不用caret的话,直接手动计算更灵活,步骤如下:
- 先提取真实值和处理好的预测值,计算混淆矩阵的核心元素:
true <- test$`Fail (1=yes)` pred <- factor(pred, levels = levels(true)) # 计算TP(真阳性:真实失败,预测失败)、TN(真阴性)、FP(假阳性)、FN(假阴性) TP <- sum(true == "失败" & pred == "失败") TN <- sum(true == "未失败" & pred == "未失败") FP <- sum(true == "未失败" & pred == "失败") FN <- sum(true == "失败" & pred == "未失败") - 计算各指标:
注意:如果TP+FP=0(没预测任何失败)或TP+FN=0(真实没有失败样本),会出现除以0的情况,这时候对应指标没有实际意义,结合样本分布判断即可。# 精确率:正确预测的失败数 / 所有预测为失败的数量 precision <- TP / (TP + FP) # 召回率:正确预测的失败数 / 真实的失败总数 recall <- TP / (TP + FN) # F1-score:精确率和召回率的调和平均 f1_score <- 2 * (precision * recall) / (precision + recall)
额外建议
你的数据集样本量极小(n=32),单次80/20拆分的测试集只有7行,结果稳定性极差,还容易出现类别不平衡或预测单一的问题。建议改用k折交叉验证,比如5折(每折6-7个样本),用caret的train函数直接完成建模和交叉验证,结果更可靠:
library(caret) # 设置5折交叉验证参数 train_control <- trainControl(method = "cv", number = 5) # 训练惩罚逻辑回归模型(以glmnet为例) model <- train(`Fail (1=yes)` ~ ., data = train, method = "glmnet", trControl = train_control) # 查看模型评估结果 print(model)
内容的提问来源于stack exchange,提问作者Shawn B
相关产品推荐
相关产品推荐

