我有一个包含 10,000 行和两列的数据框、段(具有 32 个值的因子)和目标(具有两个值“是”和“否”的因子,每个值 5,000 个)。我正在尝试使用随机森林来使用分段作为特征来对目标进行分类。
训练随机森林分类器后:
> forest <- randomForest(target ~ segment, data)
混淆矩阵强烈偏向“否”:
> print(forest$confusion)
no yes class.error
no 4872 76 0.01535974
yes 5033 19 0.99623911
在 10,000 行中,不到 100 行被分类为“是”(即使原始计数为 50/50)。如果我切换标签的名称,我会得到相反的结果:
> data$target <- as.factor(ifelse(data$target == 'yes', 'no', 'yes'))
> forest <- randomForest(target ~ segment, data = data)
> print(forest$confusion)
no yes class.error
no 4915 137 0.02711797
yes 4810 138 0.97210994
所以这不是一个真正的信号...而且,原始的交叉表是相对平衡的:
> table(data$target, data$segment)
1 10 11 12 13 14 15 16 17 18 19 2 20 21 22 23 24 25 26 27 28 29 3 30 31 32 4 5 6 7 8 9
no 1074 113 121 86 68 165 210 70 120 127 101 132 90 108 171 122 95 95 76 72 105 71 234 58 83 72 290 162 262 192 64 139
yes 1114 105 136 120 73 201 209 78 130 124 90 145 81 104 155 128 79 85 83 70 93 78 266 70 93 76 291 160 235 194 49 137
看起来 randomForest 采用第一个标签,并且几乎总是为其分配点。澄清一下,数据框是具有更多功能的更大表格的子集 - 我刚刚发现这个特定功能以某种方式导致了这个结果,无论包含多少其他功能。我想知道我是否遗漏了关于随机森林分类器的一些基本知识,或者是否存在一些编码问题或其他错误导致了这个奇怪的结果。
原始数据集可在此处作为 RDS 获取:
https://www.dropbox.com/s/rjq6lmvd78d6aot/weird_random_forest.RDS?dl=0
您的数据框架是平衡的,因为“是”和“否”总体上可能性相同。然而,
segment
的值基本上不包含有关 target
值的信息,因为“是”和“否”对于所有级别的 segment
的可能性大致相同,因此没有理由期待良好的预测来自随机森林或任何其他程序。
如果将
segment
转换为数字,则 randomForest
大约 65% 的时间预测“是”。大约 63% 的数据采用 segment
值,其中“是”的可能性(稍微)比“否”更大,因此这可以解释当 segment
为数字时“是”预测的高比率。但无论 segment
是数字还是因子,总体错误率都大致相同。我不确定为什么当 randomForest
是一个因素时,segment
几乎总是选择“否”。
我相信,当分段是一个因素时,随机森林几乎总是选择“否”,因为当结果类别大小存在任何不平等时,随机森林会产生扭曲的错误率、敏感性和特异性。因此,虽然您的数据“相对”平衡,但它们并不完全平衡;数据集中最常见的结果类别将在预测中受到强烈青睐。如果在预测变量和结果之间没有真正的关系时将平衡数据发送到 randomForest(),您将在预测类别中获得更多随机波动。
参见 Malley 等人。生物医学数据的统计学习。 2011.剑桥大学出版社对使用随机森林分类时的数据平衡进行更完整的讨论。
# create dataset balanced on outcome, random predictor values
data<-data.frame(target=rep(c("yes","no"),each=50), segment=sample(1:5, 100, replace=T))
table(data$target, data$segment)
table(data$target)
data$segment<- as.factor(data$segment)
forest_run1 <- randomForest(target ~ segment, data=data)
#OOB estimate of error rate: 46%
#Confusion matrix:
#no yes class.error
#no yes class.error
#no 25 25 0.50
#yes 21 29 0.42
forest_run2 <- randomForest(target ~ segment, data=data)
#OOB estimate of error rate: 53%
#Confusion matrix:
#no yes class.error
#no 25 25 0.50
#yes 28 22 0.56
forest_run3 <- randomForest(target ~ segment, data=data)
#OOB estimate of error rate: 47%
#Confusion matrix:
#no yes class.error
#no 25 25 0.50
#yes 22 28 0.44
# COMPARE THIS TO UNBALANCED RESULTS, WHERE MORE PREVALENT CLASS ALMOST ALWAYS CHOSEN
# create dataset, unbalanced on outcome, random predictor values:
data1<-data.frame(target=sample(c("yes","no"),50, replace=T,prob=c(0.6,0.4)), segment=sample(1:5, 100, replace=T))
table(data1$target, data1$segment)
table(data1$target)
forest1 <- randomForest(target ~ segment, data=data1)
#OOB estimate of error rate: 38%
#Confusion matrix:
#no yes class.error
#no 14 30 0.6818182
#yes 8 48 0.1428571