随机森林的类非常不平衡

时间:2012-01-02 19:39:54

标签: r random-forest

我在一个大数据问题中使用随机森林,它有一个非常不平衡的响应类,所以我阅读了文档,我发现了以下参数:

strata 

sampsize

这些参数的文档很少(或者我没有运气找到它),我真的不明白如何实现它。我使用以下代码:

randomForest(x=predictors, 
             y=response, 
             data=train.data, 
             mtry=lista.params[1], 
             ntree=lista.params[2], 
             na.action=na.omit, 
             nodesize=lista.params[3], 
             maxnodes=lista.params[4],
             sampsize=c(250000,2000), 
             do.trace=100, 
             importance=TRUE)

响应是一个有两个可能值的类,第一个出现的频率高于第二个(10000:1或更高)

list.params是一个包含不同参数的列表(呃!我知道......)

嗯,问题(再次)是:我如何使用'strata'参数?我正确使用sampsize?

最后,有时我会收到以下错误:

Error in randomForest.default(x = predictors, y = response, data = train.data,  :
  Still have fewer than two classes in the in-bag sample after 10 attempts.

抱歉,如果我做了很多(也许是愚蠢的)问题......

4 个答案:

答案 0 :(得分:7)

您应该尝试使用可将不平衡程度从1:10,000降低到1:100或1:10的采样方法。您还应该减小生成的树的大小。 (目前这些是我只在记忆中重复的建议,但我会看到我是否可以追踪比我的海绵皮层更多的权威。)

减少树大小的一种方法是将“nodesize”设置得更大。有了这种程度的不平衡,你可能需要让节点大小非常大,比如5-10,000。这是rhelp中的一个主题: https://stat.ethz.ch/pipermail/r-help/2011-September/289288.html

在问题的当前状态中你有sampsize=c(250000,2000),而我认为像sampsize = c(8000,2000)这样的东西更符合我的建议。我认为您正在创建样本,其中您没有任何仅使用2000采样的组。

答案 1 :(得分:4)

有几个选择。

如果您有大量数据,请留出随机的数据样本。在一组上构建模型,然后使用另一组使用ROC曲线确定类概率的正确截止值。

您还可以对少数群体中的数据进行上采样。 SMOTE算法可能有所帮助(参见下面的参考资料和函数的DMwR包)。

您还可以使用其他技巧。 rpart()和其他一些函数可以允许不同的错误成​​本,因此您可以更多地支持少数类。您可以将此类rpart()模型包装起来,以估算随机森林正在做什么。

kernlab包中的

ksvm()也可以使用不平衡的成本(但是当你这样做时,概率估计不再是好的)。许多其他包都有设置先验的参数。你也可以调整这个来强调少数群体。

最后一个想法:基于准确性最大化模型不会让你到任何地方(你可以获得99.99%的蝙蝠)。插入符号可以根据Kappa统计数据调整模型,这在您的情况下是更好的选择。

答案 2 :(得分:4)

抱歉,我不知道如何在之前的答案上发表评论,所以我会创建一个单独的答案。

我认为问题是由数据集的高度不平衡引起的(其中一个类的情况太少)。对于RF中的每个树,算法创建bootstrap样本,该样本是该树的训练集。如果您的数据集中某个类的示例太少,那么引导程序采样将只选择一个类(主要类)的示例。因此树不能只在一个类的例子上生长。似乎10次不成功的抽样尝试有限制。 因此,DWin将不平衡程度降低到较低值(1:100或1:10)的主张是最合理的。

答案 3 :(得分:1)

非常确定我不同意从样本中删除观察结果的想法。

相反,您可以考虑使用分层样本在每次重新采样时设置每个类的固定百分比。这可以通过Caret包完成。这样,您就不会通过减少训练样本的大小来省略观察。它不允许您过度表示您的类,但会确保每个子样本都有代表性的样本。

以下是我发现的一个例子:

len_pos <- nrow(example_dataset[example_dataset$target==1,])
len_neg <- nrow(example_dataset[example_dataset$target==0,])

train_model <- function(training_data, labels, model_type, ...) {
  experiment_control <- trainControl(method="repeatedcv",
                                     number = 10,
                                     repeats = 2,
                                     classProbs = T,
                                     summaryFunction = custom_summary_function)
  train(x = training_data,
        y = labels,
        method = model_type,
        metric = "custom_score",
        trControl = experiment_control,
        verbose = F,
        ...)
}

# strata refers to which feature to do stratified sampling on.
# sampsize refers to the size of the bootstrap samples to be taken from each class. These samples will be taken as input
# for each tree. 

fit_results <- train_model(example_dataset
                           , as.factor(sprintf("c%d", as.numeric(example_dataset$target)))        
                           ,"rf"
                           ,tuneGrid = expand.grid(mtry = c( 3,5,10))
                           ,ntree=500
                           ,strata=as.factor(example_dataset$target)
                           ,sampsize = c('1'=as.integer(len_pos*0.25),'0'=as.integer(len_neg*0.8))
)