关于随机森林的文章,在互联网上铺天盖地,要么是一个简单的介绍,要么是各种抄来的代码。鲜有几篇很地道的文章介绍,也被淹没在了各种搜索排名中,本文利用R的caret包带大家完整做一次真正的“调参侠”,为后面深入理解随机森林做一个很好的示范。
首先,还是引用大家最常用的数据集iris。
library(caret)
# 此处我们按照70%,30%从总样本中随机抽样构成训练和测试集数据
data <- iris
set.seed(2019.1314)
train_data <- data[sample(1:150, 105),]
# 查看数据集
summary(train_data)
qplot(Petal.Length,Petal.Width,colour=Species,data=train_data)
# !!!此处也可以将数据集7:3分取训练集的补集
test_data <- data[sample(1:150, 45),]
接下来就是建模前调参,选优:
# 定义一个5折交叉验证
# 定义模型训练参数,method确定多次交叉检验的抽样方法,number确定了划分的重数
trControl <- trainControl(method = "cv",
number = 5,
search = "grid")
# 调参
# 选最优mtry(每棵树使用的特征个数,指定节点中用于树的变量个数,默认情况下数据集变量个数的二次方根(分类模型)或三分之一(预测模型))
set.seed(2020.1314)
# 我们从1尝试到20
tuneGrid <- expand.grid(.mtry = c(1: 20))
rf_mtry <- train(Species~.,
data = train_data,
method = "rf", # 可以用names(getModelInfo())查看所有可用方法
metric = "Accuracy", # 评估模型好坏的指标,这里我们用准确率评价
tuneGrid = tuneGrid,
trControl = trControl,
importance = TRUE,
ntree = 100)
print(rf_mtry)
# 最佳mtry=1
best_mtry <- rf_mtry$bestTune$mtry
# 选最佳maxnodes值(指定树节点的最大个数)
store_maxnode <- list()
tuneGrid <- expand.grid(.mtry = best_mtry)
for (maxnodes in c(2: 20)) {
set.seed(2020.1314)
rf_maxnode <- train(Species~.,
data = train_data,
method = "rf",
metric = "Accuracy",
tuneGrid = tuneGrid,
trControl = trControl,
importance = TRUE,
maxnodes = maxnodes,
ntree = 300)
current_iteration <- toString(maxnodes)
store_maxnode[[current_iteration]] <- rf_maxnode
}
# 最佳maxnodes=10
results_maxnode <- resamples(store_maxnode)
summary(results_maxnode)
# 选最佳nodesize值(指定树节点的最小个数,默认情况下,判别模型为1,回归模型为5;)
store_nodesize <- list()
tuneGrid <- expand.grid(.mtry = best_mtry)
for (nodesize in c(2: 20)) {
set.seed(2020.1314)
rf_nodesize <- train(Species~.,
data = train_data,
method = "rf",
metric = "Accuracy",
tuneGrid = tuneGrid,
trControl = trControl,
importance = TRUE,
maxnodes = 10,
nodesize = nodesize,
ntree = 300)
current_iteration <- toString(nodesize)
store_nodesize[[current_iteration]] <- rf_nodesize
}
# 最佳nodesize=2
results_nodesize <- resamples(store_nodesize)
summary(results_nodesize)
# 寻找最佳ntree(在森林中树的个数,默认是500)
store_maxtrees <- list()
for (ntree in c(100, 250, 300, 350, 400, 450, 500, 550, 600, 800, 1000, 2000, 3000)) {
set.seed(2020.1315)
rf_maxtrees <- train(Species~.,
data = train_data,
method = "rf",
metric = "Accuracy",
tuneGrid = tuneGrid,
trControl = trControl,
importance = TRUE,
maxnodes = 10,
ntree = ntree)
key <- toString(ntree)
store_maxtrees[[key]] <- rf_maxtrees
}
results_tree <- resamples(store_maxtrees)
# 此处300就已经有很好的准确率,可能现实中我们处理的数据要复杂的多
summary(results_tree)
选好参数后,我们下面进行建模:
# 用选好的参数建模
tuneGrid <- expand.grid(.mtry = best_mtry)
fit_rf <- train(Species~.,
train_data,
method = "rf",
metric = "Accuracy",
tuneGrid = tuneGrid,
trControl = trControl,
importance = TRUE,
ntree = 300, # 在森林中树的个数
nodesize = 2,
maxnodes = 5)
# 查看各个特征的重要程度
varImp(fit_rf)
# 对测试数据进行预测
# 最终能得到97.78%的准确率
prediction <-predict(fit_rf, test_data)
# 计算混淆矩阵
confusionMatrix(prediction, test_data$Species)
最终我们的演示数据能达到97.78%的准确率,但在现实的建模过程中,除了追求其较高的准确率外,还需要关注:
1.防止数据过拟合;
2.生物学意义或者现实应用
总之,机器学习只是一个数据探索的工具,不能一味的依靠它。
参考文章:
1.http://topepo.github.io/caret/index.html