使用caret::knn3()处理多分类预测变量时出现后端数组列名错误
错误产生机制
该报错与预测变量的分类数量无关,核心触发原因是响应变量的因子levels与训练集实际存在的类别不匹配:
- 你的最小可复现示例中,
occupmerge分类5162、9132各仅对应1条观测,当createDataPartition的随机划分刚好将这两类全部分入测试集时,训练集的响应变量train_set_occupmerge虽然保留了全局所有levels,但这两个levels在训练集中没有任何实际观测值。 - caret的
knn3训练时会自动忽略训练集中无观测的levels,模型内部存储的类别列表仅包含训练集实际出现的类别,对应预测返回的概率数组列数也和实际类别数量一致。 - 但predict阶段,函数会尝试用响应变量原始的全部levels作为预测结果的列名,此时列名数量(全局levels数)和实际返回的概率数组列数(训练集实际出现的类别数)不匹配,就触发了
dimnames长度不匹配的报错。 - 你使用二元响应变量时未触发报错,是因为二元分类下随机划分几乎不可能出现某一类完全未进入训练集的情况,自然不会出现levels和实际观测不匹配的问题。
认知澄清
你认为“测试集相比训练集多出来的分类仅用于准确率计算、不影响模型运行”的理解存在偏差:问题根源并非测试集的额外分类,而是训练集响应变量保留了无观测的levels,哪怕测试集不存在这些分类,也会触发报错。
修复方案
只需要在切分数据集后,对训练集响应变量做levels丢弃,删除无观测的levels即可,代码修改如下:
将原构造响应变量的代码:
train_set_occupmerge <- factor(df %>% pull(occupmerge))[as.numeric(train_index)] test_set_occupmerge <- factor(df %>% pull(occupmerge))[-as.numeric(train_index)]
替换为:
# 切分后重新构造训练集响应变量,自动丢弃无观测的levels train_set_occupmerge <- factor(train_set$occupmerge) # 测试集响应变量对齐训练集levels,避免后续混淆矩阵计算异常 test_set_occupmerge <- factor(test_set$occupmerge, levels = levels(train_set_occupmerge))
修改后无论随机划分结果如何,都不会再触发该报错。
内容的提问来源于stack exchange,提问作者ahorn
相关产品推荐
相关产品推荐

