类非常不平衡的随机森林
Posted
技术标签:
【中文标题】类非常不平衡的随机森林【英文标题】:Random Forest with classes that are very unbalanced 【发布时间】:2012-02-01 01:04:41 【问题描述】:我在一个大数据问题中使用随机森林,它的响应类非常不平衡,所以我阅读了文档,发现了以下参数:
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.
对不起,如果我做了这么多(也许是愚蠢的)问题......
【问题讨论】:
根据DWin的建议,我将尝试对数据进行描述。数据框的大小为 1 Mrows 或更多(2 或 3 Mrows),它有近 33 列是因子,除了两个是数字类型的,还有一个额外的列是响应,一个因子有两个可能的值。我希望这会有所帮助。 在对您收到的错误消息的描述感到困惑之后,我扫描了 CRAN 上的源代码,最后联系了包作者。事实证明,实际上代码中有一个小错误会引发可能一直给您带来问题的错误。在接下来的几天里尝试检查 CRAN 的补丁版本,看看是否有帮助。 @joran 哇,谁知道呢!让我用原始代码再试一次。谢谢! 很抱歉花了这么长时间才回答,但它现在可以工作了。正如@joran 所说,这是一个错误......再次感谢 【参考方案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))
)
【讨论】:
【参考方案2】:抱歉,我不知道如何对之前的答案发表评论,所以我将创建一个单独的答案。
我认为问题是由数据集的高度不平衡引起的(其中一个类的情况太少)。对于 RF 中的每棵树,该算法都会创建引导样本,这是该树的训练集。如果您的数据集中某一类的示例太少,那么引导抽样将只选择一个类(主要类)的示例。因此,树不能仅在一个类示例上生长。似乎对 10 次不成功的采样尝试有限制。 所以 DWin 提出的将不平衡程度降低到较低值(1:100 或 1:10)的提议是最合理的。
【讨论】:
谢谢 DrDom(多写一个字母,这将是一个很棒的昵称,顺便说一下,我有点喜欢 Doom 博士)但是在哪里可以减少不平衡呢?在从数据库或 sampsize 属性中获取数据时?我尝试了第二个(我的意思是留下 1M 行或其他东西)并平衡样本大小并且错误再次出现,但是如果我从 1Mrows 减少到让说 250K 一切正常,但我担心可预测性或可能过度拟合...您的意见是什么? @nanounanue,我可以建议将所有次要类对象从主要类中添加 100 倍以上的对象(主要类对象的选择可以随机或监督进行),并开发一个模型.然后重复此步骤多次,以至少一次使用主要类中的所有对象。因此,您将拥有一包模型。所有这些都应该用于预测。您通过多数投票方案做出的最终预测——哪个班级拥有更多的选票。另一种可能性是减少主要类对象的数量。这可以根据例如聚类分析来完成。【参考方案3】:有几个选项。
如果您有大量数据,请留出数据的随机样本。在一组上构建您的模型,然后使用另一组使用 ROC 曲线确定类别概率的适当截止值。
您还可以对少数类中的数据进行上采样。 SMOTE 算法可能会有所帮助(请参阅下面的参考资料和函数的 DMwR 包)。
您还可以使用其他技术。 rpart()
和其他一些功能可以允许对错误产生不同的成本,因此您可以更偏爱少数类。您可以打包这种类型的rpart()
模型来近似随机森林正在做什么。
kernlab 包中的ksvm()
也可以使用不平衡成本(但这样做时概率估计不再有效)。许多其他包都有设置先验的参数。您也可以对此进行调整以更加强调少数类。
最后一个想法:基于准确性最大化模型不会让您有任何收获(您可以立即获得 99.99% 的收益)。插入符号可以根据 Kappa 统计量调整模型,在您的情况下这是一个更好的选择。
【讨论】:
【参考方案4】:您应该尝试使用将不平衡程度从 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 进行采样的组。
【讨论】:
谢谢DWin,你能给我一些代码示例吗?提前感谢(再次) 我通常只在给定数据或足够清晰的描述来支持构建与问题匹配的示例时才尝试编写代码。 对于您的回答,如果我增加节点大小的大小,它不会影响预测吗?我的意思是,它会降低准确性?另一方面,如果我减小树的大小,它如何提高准确性? 我怀疑在这种情况下是否可以提高您预测的准确性。与逻辑回归类似,其中较小的结果组通常应至少是预测变量数量的 10 倍。 嗨 DWin,我仍然收到错误消息: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.
我认为问题出在 sampsize ... 有什么想法吗?以上是关于类非常不平衡的随机森林的主要内容,如果未能解决你的问题,请参考以下文章