在R中更快地获得随机森林回归
我必须使用R中的randomforest进行回归。我的问题是我的数据帧非常大:我有12个变量和超过400k个条目。当我尝试(代码写在底部)得到一个随机森林回归时,系统需要很多小时来处理数据:经过5、6个小时的计算后,我不得不停止操作而没有任何输出。有人可以建议我如何更快地完成它? 谢谢在R中更快地获得随机森林回归,r,regression,random-forest,R,Regression,Random Forest,我必须使用R中的randomforest进行回归。我的问题是我的数据帧非常大:我有12个变量和超过400k个条目。当我尝试(代码写在底部)得到一个随机森林回归时,系统需要很多小时来处理数据:经过5、6个小时的计算后,我不得不停止操作而没有任何输出。有人可以建议我如何更快地完成它? 谢谢 库(插入符号) 图书馆(森林) dataset因为您使用的是插入符号,所以可以使用方法=“parRF”。这是并行随机林的一个实现 例如: library(caret) library(randomForest)
库(插入符号)
图书馆(森林)
dataset因为您使用的是插入符号,所以可以使用方法=“parRF”。这是并行随机林的一个实现
例如:
library(caret)
library(randomForest)
library(doParallel)
cores <- 3
cl <- makePSOCKcluster(cores)
registerDoParallel(cl)
dataset <- read.csv("/home/anonimo/Modelli/total_merge.csv", header=TRUE)
dati <- data.frame(dataset)
attach(dati)
trainSet <- dati[2:107570,]
testSet <- dati[107570:480343,]
# 3 times cross validation.
my_control <- trainControl(method = "cv", number = 3 )
my_forest <- train(Clip_pm25 ~ e_1 + Clipped_so + Clip_no2 + t2m_1 + tp_1 + Clipped_nh + Clipped_co + Clipped_o3 + ssrd_1 + Clipped_no + Clip_pm10 + sp_1, ,
data = trainSet,
method = "parRF",
ntree = 250,
trControl=my_control)
库(插入符号)
图书馆(森林)
图书馆(双平行)
cores我不认为在一台PC上并行(2-4核)是解决办法。有很多挂得较低的水果可以摘
1) 射频模型的复杂性随着训练样本的增加而增加。平均树深度类似于log(480000/5)/log(2)=16.5个中间节点。在绝大多数示例中,每棵树2000-10000个样本是可以的。如果你想在kaggle比赛中获胜,一个小小的额外表现真的很重要,因为赢家通吃。实际上,你可能不需要这样做
2) 不要在R代码中克隆数据集,尽量只保留数据集的一个副本(通过引用传递当然可以)。对于这个数据集来说,这不是什么大问题,因为即使对于R来说,数据集也没有那么大(~38Mb)
3) 对于大型数据集,不要使用带有randomForest算法的公式接口。它将生成数据集的额外副本。但记忆也不是什么大问题
4) 使用更快的RF算法:外部树,ranger或Rborist可用于R。外部树不完全是RF算法,但非常接近
5) 避免使用超过10个类别的分类功能。RF最多可以处理32次,但由于必须评估任何2^32次可能的拆分,因此速度会变得非常慢外部树和Rborist只通过测试一些随机选择的拆分来处理更多类别(这很好)。另一个解决方案是在python sklearn中,为每个类别分配一个唯一的整数,并将该特性作为数字处理。在运行randomForest之前,您可以使用as.numeric转换分类功能,以执行相同的操作
6) 对于更大的数据。将数据集拆分为随机块,并在每个块上训练几棵(~10棵)树。合并森林或单独保存森林。这将略微增加树的相关性。有一些很好的集群实现可以像这样训练。但对于低于1-100Gb的数据集,则不需要,具体取决于树的复杂性等
#下面我使用解决方案1-3)并获得几分钟的运行时间
library(randomForest)
#simulate data
dataset <- data.frame(replicate(12,rnorm(400000)))
dataset$Clip_pm25 = dataset[,1]+dataset[,2]^2+dataset[,4]*dataset[,3]
#dati <- data.frame(dataset) #no need to keep the data set, an extra time in memory
#attach(dati) #if you attach dati you don't need to write data$Clip_pm25, just Clip_pm25
#but avoid formula interface for randomForest for large data sets because it cost extra memory and time
#split data in X and y manually
y = dataset$Clip_pm25
X = dataset[,names(dataset) != "Clip_pm25"]
rm(dataset);gc()
object.size(X) #38Mb, no problemo
#if you were using formula interface
#output.forest <- randomForest(dati$Clip_pm25 ~ dati$e_1 + dati$Clipped_so + dati$Clip_no2 + dati$t2m_1 + dati$tp_1 + dati$Clipped_nh + dati$Clipped_co + dati$Clipped_o3 + dati$ssrd_1 + dati$Clipped_no + dati$Clip_pm10 + dati$sp_1, data=trainSet, ntree=250)
#output.forest <- randomForest(dati$Clip_pm25 ~ ., ntree=250) # use dot to indicate all variables
#start small, and scale up slowly
rf = randomForest(X,y,sampsize=1000,ntree=5) #runtime ~15 seconds
print(rf) #~67% explained var
#you probably really don't need to exeed 5000-10000 samples per tree, you could grow 2000 trees to sample most of training set
rf = randomForest(X,y,sampsize=5000,ntree=500) # runtime ~5 minutes
print(rf) #~87% explained var
#regarding parallel
#here you could implement some parallel looping
#.... but is it really worth for a 2-4 x speedup?
#coding parallel on single PC is fun but rarely worth the effort
#If you work at some company or university with a descent computer cluster,
#then you can spawn the process across 20-80-200 nodes and get a ~10-60-150 x speedup
#I can recommend the BatchJobs package
库(随机林)
#模拟数据
数据集其他两个答案都很好。另一种选择是实际使用为高维/高容量数据集专门构建的最新包。他们使用低级语言(C++和/或Java)运行代码,在某些情况下使用并行化
我建议您考虑以下三点:
RangER(使用C++编译器)
RoopFracestSRC(使用C++编译器)
h2o(Java编译器-需要Java版本8或更高版本)
此外,这里还有一些额外的阅读资料,让您在选择哪种套餐时有更多的选择:
第8页显示了显示ranger相对于randomForest针对不断增长的数据大小的性能改进的基准-ranger由于运行时的线性增长而比randomForest针对不断增长的树/样本/拆分/特征大小的非线性增长快得多
祝你好运 请尝试ranger
或Rborist
谢谢您的回答,但当我尝试计算我的林:总结错误时,此代码返回错误。连接(连接):无效连接R并行实现的一个缺点是它必须启动一个新实例并将数据复制到每个实例。如果使用商品硬件,这可能会很快导致内存问题。@p如果必须计算for,则我的新代码出现错误:未序列化错误(socklist[[n]]):从连接读取错误。@Lupanoide,请尝试重新启动r会话。另请参阅并感谢phiver,现在它从5分钟开始工作。我希望它能很快完成,我会告诉你最新情况
foreach_forest <- foreach(ntree=rep(250, cores),
.combine=combine,
.multicombine=TRUE,
.packages="randomForest") %dopar%
randomForest(Clip_pm25 ~ e_1 + Clipped_so + Clip_no2 + t2m_1 + tp_1 + Clipped_nh + Clipped_co + Clipped_o3 + ssrd_1 + Clipped_no + Clip_pm10 + sp_1,
data = trainSet, ntree=ntree)
# don't forget to stop the cluster
stopCluster(cl)
library(randomForest)
#simulate data
dataset <- data.frame(replicate(12,rnorm(400000)))
dataset$Clip_pm25 = dataset[,1]+dataset[,2]^2+dataset[,4]*dataset[,3]
#dati <- data.frame(dataset) #no need to keep the data set, an extra time in memory
#attach(dati) #if you attach dati you don't need to write data$Clip_pm25, just Clip_pm25
#but avoid formula interface for randomForest for large data sets because it cost extra memory and time
#split data in X and y manually
y = dataset$Clip_pm25
X = dataset[,names(dataset) != "Clip_pm25"]
rm(dataset);gc()
object.size(X) #38Mb, no problemo
#if you were using formula interface
#output.forest <- randomForest(dati$Clip_pm25 ~ dati$e_1 + dati$Clipped_so + dati$Clip_no2 + dati$t2m_1 + dati$tp_1 + dati$Clipped_nh + dati$Clipped_co + dati$Clipped_o3 + dati$ssrd_1 + dati$Clipped_no + dati$Clip_pm10 + dati$sp_1, data=trainSet, ntree=250)
#output.forest <- randomForest(dati$Clip_pm25 ~ ., ntree=250) # use dot to indicate all variables
#start small, and scale up slowly
rf = randomForest(X,y,sampsize=1000,ntree=5) #runtime ~15 seconds
print(rf) #~67% explained var
#you probably really don't need to exeed 5000-10000 samples per tree, you could grow 2000 trees to sample most of training set
rf = randomForest(X,y,sampsize=5000,ntree=500) # runtime ~5 minutes
print(rf) #~87% explained var
#regarding parallel
#here you could implement some parallel looping
#.... but is it really worth for a 2-4 x speedup?
#coding parallel on single PC is fun but rarely worth the effort
#If you work at some company or university with a descent computer cluster,
#then you can spawn the process across 20-80-200 nodes and get a ~10-60-150 x speedup
#I can recommend the BatchJobs package