我怎样才能加快我的随机森林的训练?
How can I speed up the training of my random forest?
我正在尝试训练几个 运行dom 森林(用于回归)让它们竞争并查看哪些特征选择和哪些参数提供最佳模型。
然而,培训似乎花费了大量时间,我想知道我是否做错了什么。
我用于训练的数据集(下面称为 train
)有 217k 行和 58 列(其中只有 21 列在 运行dom 森林中用作预测变量。它们是所有 numeric
或 integer
,但布尔值除外,它是 class 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 内存,我想我可以尝试并行化训练,遵循 this answer(但是,我使用了 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 倍...
- 这正常吗?
- 如果不是,我可以用我的数据 and/or 我的代码做些什么来从根本上减少 运行 宁时间吗?
- 如果没有,我应该告诉负责服务器的人它应该快得多吗?
感谢您的回答。
备注:
- 我是唯一一个使用此服务器的人
- 对于我的下一个测试,我将删除 运行dom 林中未使用的列
- 我很晚才意识到我可以通过调用
randomForest(predictors,decision)
而不是 randomForest(decision~.,data=input)
来缩短 运行ning 时间,我会从现在开始这样做,但我认为我上面的问题仍然存在。
虽然我是蛮力技术的粉丝,例如并行化或 运行 长时间使用代码,但我更喜欢改进算法以避免必须使用蛮力技术。
虽然使用 2000 棵树训练随机森林开始变得非常昂贵,但使用较少数量的树进行训练花费的时间更合理。对于初学者,您可以使用 4
、8
、16
、32
、...
、256
、512
树进行训练并仔细观察让你知道模型有多稳健的指标。这些指标包括最佳常数模型(您的森林在数据集上的表现与预测所有输入的中值的模型的表现如何),以及袋外误差。此外,您可以观察最重要的预测变量及其重要性,以及当您添加更多树时是否开始在那里看到收敛。
理想情况下,您不必使用数千棵树来构建模型。一旦你的模型开始收敛,添加更多树不一定会使模型恶化,但同时它不会添加任何新信息。通过避免使用太多的树,您可以将需要一周左右的计算时间缩短到不到一天的时间。如果除此之外,您还利用了十几个 CPU 核心,那么您可能会在几个小时内看到一些东西。
要查看每个随机森林 运行 之后的变量重要性,您可以尝试以下方法:
fit <- randomForest(...)
round(importance(fit), 2)
据我了解,前 5-10 个预测变量对模型的影响最大。如果您注意到通过增加树,这些顶级预测变量并没有真正改变彼此的相对位置,并且重要性指标似乎保持不变,那么您可能要考虑不使用那么多树。
randomForest()
函数可以使用 "formula interface" 或 "matrix interface" 接受数据。众所周知,矩阵接口可以提供更好的性能数据。
公式界面:
rf.formula = randomForest(Species ~ ., data = iris)
矩阵接口:
rf.matrix = randomForest(y = iris[, 5], x = iris[, 1:4])
其他两个答案都不错。另一种选择是实际使用专为高维度/大容量数据集构建的更新包。他们 运行 他们的代码使用低级语言 (C++ and/or Java),并且在某些情况下使用并行化。
我建议看看这三个:
- ranger(使用 C++ 编译器)
- randomForestSRC(使用 C++ 编译器)
- h2o(Java 编译器 - 需要 Java 版本 8 或更高版本)
此外,这里还有一些额外的阅读内容可以让您更多地了解选择哪个包:
https://arxiv.org/pdf/1508.04409.pdf
第 8 页显示的基准显示了 ranger 相对于 randomForest 在数据量不断增长时的性能改进 - 由于 运行 时间的线性增长而不是 randomForest 的非线性增长,ranger 的速度要快得多上升 tree/sample/split/feature 尺寸。
祝你好运!
我正在尝试训练几个 运行dom 森林(用于回归)让它们竞争并查看哪些特征选择和哪些参数提供最佳模型。
然而,培训似乎花费了大量时间,我想知道我是否做错了什么。
我用于训练的数据集(下面称为 train
)有 217k 行和 58 列(其中只有 21 列在 运行dom 森林中用作预测变量。它们是所有 numeric
或 integer
,但布尔值除外,它是 class 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 内存,我想我可以尝试并行化训练,遵循 this answer(但是,我使用了 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 倍...
- 这正常吗?
- 如果不是,我可以用我的数据 and/or 我的代码做些什么来从根本上减少 运行 宁时间吗?
- 如果没有,我应该告诉负责服务器的人它应该快得多吗?
感谢您的回答。
备注:
- 我是唯一一个使用此服务器的人
- 对于我的下一个测试,我将删除 运行dom 林中未使用的列
- 我很晚才意识到我可以通过调用
randomForest(predictors,decision)
而不是randomForest(decision~.,data=input)
来缩短 运行ning 时间,我会从现在开始这样做,但我认为我上面的问题仍然存在。
虽然我是蛮力技术的粉丝,例如并行化或 运行 长时间使用代码,但我更喜欢改进算法以避免必须使用蛮力技术。
虽然使用 2000 棵树训练随机森林开始变得非常昂贵,但使用较少数量的树进行训练花费的时间更合理。对于初学者,您可以使用 4
、8
、16
、32
、...
、256
、512
树进行训练并仔细观察让你知道模型有多稳健的指标。这些指标包括最佳常数模型(您的森林在数据集上的表现与预测所有输入的中值的模型的表现如何),以及袋外误差。此外,您可以观察最重要的预测变量及其重要性,以及当您添加更多树时是否开始在那里看到收敛。
理想情况下,您不必使用数千棵树来构建模型。一旦你的模型开始收敛,添加更多树不一定会使模型恶化,但同时它不会添加任何新信息。通过避免使用太多的树,您可以将需要一周左右的计算时间缩短到不到一天的时间。如果除此之外,您还利用了十几个 CPU 核心,那么您可能会在几个小时内看到一些东西。
要查看每个随机森林 运行 之后的变量重要性,您可以尝试以下方法:
fit <- randomForest(...)
round(importance(fit), 2)
据我了解,前 5-10 个预测变量对模型的影响最大。如果您注意到通过增加树,这些顶级预测变量并没有真正改变彼此的相对位置,并且重要性指标似乎保持不变,那么您可能要考虑不使用那么多树。
randomForest()
函数可以使用 "formula interface" 或 "matrix interface" 接受数据。众所周知,矩阵接口可以提供更好的性能数据。
公式界面:
rf.formula = randomForest(Species ~ ., data = iris)
矩阵接口:
rf.matrix = randomForest(y = iris[, 5], x = iris[, 1:4])
其他两个答案都不错。另一种选择是实际使用专为高维度/大容量数据集构建的更新包。他们 运行 他们的代码使用低级语言 (C++ and/or Java),并且在某些情况下使用并行化。
我建议看看这三个:
- ranger(使用 C++ 编译器)
- randomForestSRC(使用 C++ 编译器)
- h2o(Java 编译器 - 需要 Java 版本 8 或更高版本)
此外,这里还有一些额外的阅读内容可以让您更多地了解选择哪个包: https://arxiv.org/pdf/1508.04409.pdf
第 8 页显示的基准显示了 ranger 相对于 randomForest 在数据量不断增长时的性能改进 - 由于 运行 时间的线性增长而不是 randomForest 的非线性增长,ranger 的速度要快得多上升 tree/sample/split/feature 尺寸。
祝你好运!