【问题标题】:How to improve randomForest performance?如何提高随机森林性能?
【发布时间】:2014-05-29 07:44:48
【问题描述】:

我有一个大小为 38 MB 的训练集(12 个属性,420000 行)。我正在运行下面的R sn-p,使用randomForest 训练模型。这对我来说需要几个小时。

rf.model <- randomForest(
              Weekly_Sales~.,
              data=newdata,
              keep.forest=TRUE,
              importance=TRUE,
              ntree=200,
              do.trace=TRUE,
              na.action=na.roughfix
            )

我认为,由于na.roughfix,执行需要很长时间。训练集中有这么多NA's

有人可以告诉我如何提高性能吗?

我的系统配置是:

Intel(R) Core i7 CPU @ 2.90 GHz
RAM - 8 GB
HDD - 500 GB
64 bit OS

【问题讨论】:

  • 至关重要的是,您没有告诉我们 F、特征数或数据中的列数;请参阅下文了解为什么 F 的影响是二次的。 (但它看起来像 Kaggle Walmart Store Sales 数据集。在该数据中,train.csv 只有 Store, Dept, IsHolidayfeatures.csv添加了 10 个功能,其中大部分都没用。添加您自己的用户生成的功能,F 可以是 4 到 50+ 之间的任何值......就像我一直在敲门一样,它会产生巨大的差异。积极地找出低-重要性特征是并且排除它们,至少对于探索,而不是最终模型生成。)

标签: r performance random-forest


【解决方案1】:

(tl;dr 是您应该 a)将节点大小增加到 >> 1 和 b)排除非常低重要性的特征列,甚至可能排除(例如)80% 的列。您的问题几乎肯定不是na.roughfix,但如果您怀疑,请在调用randomForest 之前单独运行na.roughfix 作为独立步骤。首先把那条红鲱鱼移开。)

现在,以下所有建议仅在您超出内存限制之前适用,因此请测量您的内存使用情况,并确保您没有超出。 (从可笑的小参数开始,然后放大它们,测量运行时间,并不断检查它没有不成比例地增加。)

影响randomForest性能的主要参数有:

  • mtry(越少越好)
  • ntrees
  • 数据中的特征数量/cols - 越多越慢,或者更糟!见下文
  • 数据中的观察/行数
  • ncores(越多越快 - 只要使用并行选项)
  • 通过设置importance=F 和proximity=F 来提升一些性能(不计算邻近矩阵)
  • 永远不要使用疯狂的默认 nodesize=1 进行分类!在 Breiman 的包中,您不能直接设置 maxdepth,而是使用 nodesize 作为代理,并阅读所有好的建议:CrossValidated: "Practical questions on tuning Random Forests"
  • 所以这里你的数据有 4.2e+5 行,那么如果每个节点不应该小于 ~0.1%,试试nodesize=42。 (首先尝试 nodesize=420 (1%),看看它有多快,然后重新运行,将 nodesize 调低。根据经验确定此数据集的合适 nodesize。)
  • 运行时间与 ~ 2^D_max 成正比,即多项式与 (-log1p(nodesize))
  • 您还可以选择使用采样来加速,请参阅strata,sampsize 参数

那么运行时的一阶估计,表示 mtry=M,ntrees=T,ncores=C,nfeatures=F,nrows=R,maxdepth=D_max,是:

Runtime proportional to: T * F^2 * (R^1.something) * 2^D_max / C

(同样,如果您超出内存,所有赌注都将被取消。另外,请尝试仅在一个内核上运行,然后是 2,然后是 4,并验证您确实获得了线性加速。而不是减速。) (大 R 的效果比线性差,可能是二次的,因为树分区必须考虑数据行的所有分区;当然它比线性差一些。通过使用采样或索引来检查是否只给它说 10%行)。

提示:保持大量低重要性特征会二次增加运行时间,从而实现亚线性的准确性提高。这是因为在每个节点上,我们必须考虑所有可能的特征选择(或 mtry 允许的任何数量)。在每棵树中,我们必须考虑所有(F-choose-mtry)可能的特征组合。 所以这是我的方法,做“快速和肮脏的性能选择”:

  1. 正常生成树(慢),尽管使用理智的nodesize=42 或更大
  2. 查看 rf$importances 或 randomForest::varImpPlot()。只选择 top-K 特征,在哪里选择 K;对于一个愚蠢的快速示例,选择 K=3。保存整个列表以供将来参考。
  3. 现在重新运行树,但只给它newdata[,importantCols]
  4. 确认速度是二次方更快,并且 oob.error 也不会差很多
  5. 一旦知道变量的重要性,就可以关闭importance=F
  6. 调整 mtry 和 nodesize(一次调整一个),重新运行并衡量速度改进
  7. 在对数轴上绘制性能结果
  8. 将结果发布给我们!你证实了上面的说法吗?有没有关于内存使用的 cmets?

(请注意,对于实际的特征选择,以上不是一个统计上有效的过程,不要依赖它,阅读 randomForest 包以了解基于 RF 的特征选择的实际正确方法。)

【讨论】:

  • 很棒的答案,太糟糕了@user3497321 再也回不来了。
【解决方案2】:

我怀疑 do.trace 也可能会消耗时间...而不是 do.trace = TRUE,您可以使用 do.trace = 5(仅显示 5 条跟踪)来了解错误。对于大型数据集,do.trace 也会占用大量时间。

【讨论】:

    【解决方案3】:

    我注意到的另一个想法:
    正确的是ntrees,而不是ntree
    randomForest 包的默认值为 500

    【讨论】:

      【解决方案4】:

      另一种选择是实际使用专门为高维/大容量数据集构建的更新包。他们使用较低级别的语言(C++ 和/或 Java)运行他们的代码,并且在某些情况下使用并行化。

      我建议看看这三个:

      ranger(使用 C++ 编译器) randomForestSRC(使用 C++ 编译器) h2o(Java 编译器 - 需要 Java 8 或更高版本) 此外,这里还有一些额外的阅读资料,可以让您更多地了解选择哪个包:https://arxiv.org/pdf/1508.04409.pdf

      第 8 页显示了一些基准,显示了 ranger 对 randomForest 的性能改进,以应对不断增长的数据量 - 由于运行时的线性增长,ranger 的速度要快得多,而不是 randomForest 的非线性增长,因为树/样本/拆分/特征大小的增加。

      祝你好运!

      【讨论】:

        猜你喜欢
        • 2020-03-12
        • 2016-03-25
        • 2020-09-16
        • 2015-05-22
        • 2019-02-26
        • 2016-06-24
        • 2014-11-01
        • 1970-01-01
        • 2017-12-04
        相关资源
        最近更新 更多