如何加快对随机森林的训练?

时间:2016-05-12 14:36:28

标签: r parallel-processing random-forest doparallel parallel-foreach

我试图训练几个随机森林(用于回归)让他们竞争,看看哪个特征选择以及哪些参数给出最佳模型。

然而,培训似乎需要花费大量时间,而且我想知道我是否做错了什么。

我用于训练的数据集(下面称为train)有217k行和58列(其中只有21列作为随机林中的预测变量。它们全部是{{ 1}}或numeric,但布尔值除外,属于integer类。character输出为y)。

我运行了以下代码四次,将值numeric4100500提供给2000

nb_trees

以下是他们每个人训练的时间:

library("randomForest")
nb_trees <- #this changes with each test, see above
ptm <- proc.time()
fit <- randomForest(y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 
    + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 
    + x20 + x21, 
    data = train, 
    ntree = nb_trees, 
    do.trace=TRUE)
proc.time() - ptm

由于我公司的服务器有12个核心和125个RAM,我想我可以尝试在this answer之后并行化培训(但是,我使用了nb_trees | time 4 4mn 100 1h 41mn 500 8h 40mn 2000 34h 26mn 包,因为它似乎要永远与doParallel一起运行,我不知道为什么。我无法找到doSNOW也会工作的地方,抱歉。

doParallel

当我运行它时,它比非并行化代码花费的时间更短:

library("randomForest")
library("foreach")
library("doParallel")
nb_trees <- #this changes with each test, see table below
nb_cores <- #this changes with each test, see table below
cl <- makeCluster(nb_cores)
registerDoParallel(cl)
ptm <- proc.time()
fit <- foreach(ntree = rep(nb_trees, nb_cores), .combine = combine, .packages = "randomForest") 
    %dopar% {
        randomForest(y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 
        + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 
        + x20 + x21,
        data = train, 
        ntree = ntree,
        do.trace=TRUE)}
proc.time() - ptm
stopCluster(cl)

然而,我认为它仍然需要花费很多时间,不是吗?我知道将树木组合到最后的森林中需要花费时间,因此我认为使用12个核心的速度要快12倍,但它只快2倍〜

  • 这是正常的吗?
  • 如果不是,我可以用我的数据和/或代码来彻底减少运行时间吗?
  • 如果没有,我应该告诉负责服务器的人应该更快吗?

感谢您的回答。

注意:

  • 我是唯一使用此服务器的人
  • 对于我的下一次测试,我将删除随机森林中未使用的列
  • 我意识到我可以通过拨打nb_trees | nb_cores | total number of trees | time 1 4 4 2mn13s 10 10 100 52mn 9 12 108 (closest to 100 with 12 cores) 59mn 42 12 504 (closest to 500 with 12 cores) I won't be running this one 167 12 2004 (closest to 2000 with 12 cores) I'll run it next week-end 代替randomForest(predictors,decision)来改善运行时间,而且从现在开始我会这样做,但我认为上面的问题仍然存在

3 个答案:

答案 0 :(得分:8)

虽然我喜欢蛮力技术,例如并行化或运行代码很长时间,但我更喜欢改进算法以避免使用暴力技术。

虽然使用2000棵树训练你的随机森林开始变得非常昂贵,但用较少数量的树木进行训练需要更合理的时间。对于初学者,您可以说481632...256512树并仔细观察指标,让您了解该模型的稳健性。这些指标包括最佳常量模型(森林在数据集上的表现与预测所有输入的中位数的模型相比),以及包外错误。此外,您可以观察顶部预测变量及其重要性,以及在添加更多树时是否开始看到会聚。

理想情况下,您不必使用数千棵树来构建模型。一旦您的模型开始收敛,添加更多树木不一定会使模型恶化,但同时它不会添加任何新信息。通过避免使用太多树木,您可以减少计算,该计算可能需要一周到不到一天。如果最重要的是,你利用了十几个CPU核心,那么你可能会看到几个小时的东西。

要在每次随机林运行后查看变量重要性,您可以尝试以下几行:

fit <- randomForest(...)
round(importance(fit), 2)

据我所知,首先说5-10个预测因子对模型的影响最大。如果您注意到通过增加树木,这些顶级预测变量并没有真正改变相对于彼此的位置,并且重要性指标似乎保持不变,那么您可能需要考虑不使用这么多树。

答案 1 :(得分:5)

randomForest()函数可以使用&#34;公式界面&#34;或者#34;矩阵界面&#34;。众所周知,矩阵接口可以提供更好的性能数据。

公式界面:

rf.formula = randomForest(Species ~ ., data = iris)

Matrix界面:

rf.matrix = randomForest(y = iris[, 5], x = iris[, 1:4])

答案 2 :(得分:0)

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

我建议看看这三个:

  1. 游侠(使用 C++ 编译器)
  2. randomForestSRC(使用 C++ 编译器)
  3. h2o(Java 编译器 - 需要 Java 8 或更高版本)

另外,这里有一些额外的阅读,让你更多地了解选择哪个包: https://arxiv.org/pdf/1508.04409.pdf

第 8 页显示的基准测试显示了 Ranger 相对于 randomForest 对不断增长的数据大小的性能改进 - 由于运行时的线性增长而不是 randomForest 对于上升的树/样本/分割/特征大小的非线性,ranger 的速度要快得多.

祝你好运!