我正在尝试使用随机森林来预测极其不平衡的数据集的结果(少数类比率大约只有 1% 甚至更少)。由于传统的随机森林算法将整体错误率降到最低,而不是特别关注少数类,因此不能直接适用于不平衡数据。所以我想为少数类的错误分类(成本敏感学习)分配高成本。
我阅读了几个可以在 R 中使用选项classwt
的来源randomForest
,但我不知道如何使用它。我们还有其他替代randomForest
功能吗?
我正在尝试使用随机森林来预测极其不平衡的数据集的结果(少数类比率大约只有 1% 甚至更少)。由于传统的随机森林算法将整体错误率降到最低,而不是特别关注少数类,因此不能直接适用于不平衡数据。所以我想为少数类的错误分类(成本敏感学习)分配高成本。
我阅读了几个可以在 R 中使用选项classwt
的来源randomForest
,但我不知道如何使用它。我们还有其他替代randomForest
功能吗?
这个线程是指另外两个线程和一篇关于这个问题的好文章。似乎类加权和下采样同样好。我使用如下所述的下采样。
请记住,训练集必须很大,因为只有 1% 可以表征稀有类。少于 25~50 个这个类的样本可能会有问题。很少有表征该类的样本将不可避免地使学习模式变得粗糙且可重复性降低。
RF 默认使用多数投票。训练集的类流行率将作为某种有效的先验。因此,除非稀有类是完全可分离的,否则这个稀有类在预测时不太可能赢得多数投票。您可以聚合投票分数,而不是按多数票聚合。
分层抽样可用于增加稀有类的影响。这是根据对其他类进行下采样的成本来完成的。生长的树将变得不那么深,因为需要拆分的样本更少,因此限制了学习的潜在模式的复杂性。种植的树的数量应该很大,例如 4000 棵,这样大多数观察都涉及到几棵树。
在下面的示例中,我模拟了一个包含 5000 个样本的训练数据集,其中包含 3 个类别,患病率分别为 1%、49% 和 50%。因此将有 0 类的 50 个样本。第一个图显示了训练集的真实类作为两个变量 x1 和 x2 的函数。
训练了四个模型:一个默认模型,以及三个具有 1:10:10 1:2:2 和 1:1:1 分层的分层模型。主要而每棵树中的 inbag 样本(包括重绘)的数量将是 5000、1050、250 和 150。由于我不使用多数投票,因此我不需要进行完美平衡的分层。相反,稀有类别的投票可以加权 10 倍或其他一些决策规则。您的误报和误报成本应该会影响此规则。
下图显示了分层如何影响投票分数。请注意,分层类别比率始终是预测的质心。
最后,您可以使用 ROC 曲线找到一个投票规则,该规则可以让您在特异性和敏感性之间进行良好的权衡。黑线为无分层,红色1:5:5,绿色1:2:2,蓝色1:1:1。对于这个数据集,1:2:2 或 1:1:1 似乎是最佳选择。
顺便说一句,投票分数在这里是袋外交叉验证的。
和代码:
library(plotrix)
library(randomForest)
library(AUC)
make.data = function(obs=5000,vars=6,noise.factor = .2,smallGroupFraction=.01) {
X = data.frame(replicate(vars,rnorm(obs)))
yValue = with(X,sin(X1*pi)+sin(X2*pi*2)+rnorm(obs)*noise.factor)
yQuantile = quantile(yValue,c(smallGroupFraction,.5))
yClass = apply(sapply(yQuantile,function(x) x<yValue),1,sum)
yClass = factor(yClass)
print(table(yClass)) #five classes, first class has 1% prevalence only
Data=data.frame(X=X,y=yClass)
}
plot.separation = function(rf,...) {
triax.plot(rf$votes,...,col.symbols = c("#FF0000FF",
"#00FF0010",
"#0000FF10")[as.numeric(rf$y)])
}
#make data set where class "0"(red circles) are rare observations
#Class 0 is somewhat separateble from class "1" and fully separateble from class "2"
Data = make.data()
par(mfrow=c(1,1))
plot(Data[,1:2],main="separation problem: identify rare red circles",
col = c("#FF0000FF","#00FF0020","#0000FF20")[as.numeric(Data$y)])
#train default RF and with 10x 30x and 100x upsumpling by stratification
rf1 = randomForest(y~.,Data,ntree=500, sampsize=5000)
rf2 = randomForest(y~.,Data,ntree=4000,sampsize=c(50,500,500),strata=Data$y)
rf3 = randomForest(y~.,Data,ntree=4000,sampsize=c(50,100,100),strata=Data$y)
rf4 = randomForest(y~.,Data,ntree=4000,sampsize=c(50,50,50) ,strata=Data$y)
#plot out-of-bag pluralistic predictions(vote fractions).
par(mfrow=c(2,2),mar=c(4,4,3,3))
plot.separation(rf1,main="no stratification")
plot.separation(rf2,main="1:10:10")
plot.separation(rf3,main="1:5:5")
plot.separation(rf4,main="1:1:1")
par(mfrow=c(1,1))
plot(roc(rf1$votes[,1],factor(1 * (rf1$y==0))),main="ROC curves for four models predicting class 0")
plot(roc(rf2$votes[,1],factor(1 * (rf1$y==0))),col=2,add=T)
plot(roc(rf3$votes[,1],factor(1 * (rf1$y==0))),col=3,add=T)
plot(roc(rf4$votes[,1],factor(1 * (rf1$y==0))),col=4,add=T)