14

我正在尝试训练几个随机森林(用于回归)以让它们竞争并查看哪些特征选择和哪些参数提供了最佳模型。

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

我用于训练的数据集(train下面称为)有 217k 行和 58 列(其中只有 21 个用作随机森林中的预测变量。它们都是numericor integer,除了布尔值,它是类character.y输出是numeric)。

我运行了以下代码四次,将值4, 100, 500,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

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

nb_trees | time
4          4mn
100        1h 41mn
500        8h 40mn
2000       34h 26mn

由于我公司的服务器有 12 个内核和 125Go 的 RAM,我想我可以按照这个答案尝试并行化训练(但是,我使用了这个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)

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

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

但是,我认为这仍然需要很多时间,不是吗?我知道将树木组合成最终的森林需要时间,所以我没想到 12 核的速度会快 12 倍,但它只快了 ~ 2 倍......

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

感谢您的回答。

备注:

  • 我是唯一使用此服务器的人
  • 对于我的下一个测试,我将摆脱随机森林中未使用的列
  • 我很晚才意识到我可以通过调用randomForest(predictors,decision)而不是来改善运行时间randomForest(decision~.,data=input),我将从现在开始这样做,但我认为我上面的问题仍然存在。
4

3 回答 3

9

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

虽然使用 2000 棵树训练您的随机森林开始变得异常昂贵,但使用较少数量的树进行训练需要更合理的时间。对于初学者,您可以使用 , , , , , 树进行训练4816仔细32观察...指标256512这些指标可以让您了解模型的鲁棒性。这些指标包括最佳常数模型(您的森林在数据集上的表现与预测所有输入的中位数的模型的表现如何),以及袋外误差。此外,您可以观察顶级预测变量及其重要性,以及当您添加更多树时是否开始看到收敛。

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

要查看每次随机森林运行后的变量重要性,您可以尝试以下方法:

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

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

于 2016-05-12T14:54:45.157 回答
5

randomForest()函数可以使用“公式接口”或“矩阵接口”来接受数据。众所周知,矩阵接口可以提供更好的性能数据。

公式界面:

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

矩阵界面:

rf.matrix = randomForest(y = iris[, 5], x = iris[, 1:4])
于 2016-05-12T18:56:25.810 回答
1

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

我建议看看这三个:

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

此外,这里还有一些额外的阅读资料,让您了解更多关于选择哪个包的信息: https ://arxiv.org/pdf/1508.04409.pdf

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

祝你好运!

于 2021-01-07T22:44:37.750 回答