多分类回归混淆矩阵未正确显示实际值计数问题求助
嘿,我来帮你拆解这个问题——你遇到的核心问题其实和R里因子的默认行为有关,咱们一步步理清楚:
问题到底出在哪?
你提到实际值的第8水平有55条观测,但预测值里这个水平的观测数为0。这里的关键是:当predict()生成的结果里完全没有某个因子水平的观测时,R会自动把这个空水平从因子里移除掉!
所以你最开始得到的sc_fitted1,其实根本没有第8这个因子水平——哪怕你后来手动用levels(sc_fitted1) <- levels(sc$LeagueIndex)把水平加回去,也只是给因子添了个“空标签”,对应的观测数还是0。这就导致:
- 没手动设水平时,
table()和confusionMatrix()会直接忽略预测向量里不存在的水平,看起来实际值的第8水平“消失”了 - 设了水平后,虽然水平显示出来了,但因为预测侧没有观测,展示逻辑会有点错位,但实际值的列合计其实是对的,只是你可能没注意到预测的第8行全是0
怎么解决?
要让混淆矩阵完整显示所有8个水平,且实际值的合计和真实计数完全匹配,你需要确保预测向量和参考向量的因子水平完全对齐,而且空水平不会被自动丢弃。这里有两种简单的方法:
方法1:预测时直接指定因子水平
在生成预测结果后,直接用factor()强制指定所有水平,避免R自动删除空水平:
sc_fitted1 <- predict(sc_mod1, sc) # 强制对齐参考向量的所有因子水平 sc_fitted1 <- factor(sc_fitted1, levels = levels(sc$LeagueIndex))
方法2:用forcats包的fct_expand()(更省心)
forcats包专门处理因子操作,fct_expand()可以安全地添加缺失的水平,不会改变现有数据:
library(forcats) sc_fitted1 <- fct_expand(sc_fitted1, levels(sc$LeagueIndex))
验证效果
做完上面的操作后,再运行你的验证代码:
confusionMatrix(data = sc_fitted1, reference = sc$LeagueIndex) table(predicted = sc_fitted1, actual = sc$LeagueIndex)
这时候你会看到完整的8x8混淆矩阵,实际值的每一列合计都会和table(sc$LeagueIndex)完全一致,预测的第8行全为0,完全符合你的预期。
额外提一句:为什么手动改levels没用?
直接用levels(sc_fitted1) <- ...只是修改了因子的属性标签,但没有重新构造因子对象,R还是不会把空水平当成“有效”的水平来统计。而factor()或fct_expand()是重新生成因子,明确告诉R要保留所有指定的水平,哪怕没有观测。
另外,你的模型完全没预测出第8水平,大概率是因为这个水平的样本量太少(只有55条),模型很难学到区分它的特征。如果需要提升对这个类别的预测能力,可以考虑试试过采样(比如SMOTE)或者调整模型的参数哦。
内容的提问来源于stack exchange,提问作者dkae

