我目前正在使用Python进行随机森林回归器模型:
rfr = RandomForestRegressor(random_state=42)
param_grid = {'bootstrap': [True],
'max_depth': [10, 30, 50],
'n_estimators': [200, 400, 600]}
CV = RandomizedSearchCV(estimator = rfr, param_distributions = param_grid, n_iter = 5, cv = 5, verbose=2, random_state=42, n_jobs = -1)
CV.fit(x_train, y_train)
print('best model:', CV.best_params_,'nbest score: %.2f' % CV.best_score_)
如何在 R 中重新编码它们?特别是对于 RFR、param_grid 和 CV?
你最好的选择将是caret
包。这个包实际上没有模型,它就像一个框架。例如,训练caret
模型时,默认模型来自randomForest::randomForest
。
不需要或建议进行编码。我不知道有任何模型需要您在 R 中编码分类数据。但是,确保数据中的数据类型正确始终很重要。
使用这些方法没有实例化。
以下是您需要查看的一些关键功能以及caret
库中的原因。
createDataPartition
:拆分数据;训练/测试/验证(随心所欲)train
:训练模型trainControl
:用于设置是否要引导,交叉验证,重复交叉验证(以及更多),要执行的操作次数以及重复次数。modelLookup
:这将告诉您想要可以为您选择的模型类型设置控件。例如,如果你想使用randomForest::randomForest
,modelLookup
告诉我们你只能网格mtry
;如果你使用ranger::ranger
(另一个库的随机森林),modelLookup
告诉我们你可以网格mtry
、splitrule
和min.node.size
。(这两种随机森林模型都适用于分类和回归。
有一个很棒的数字手册caret
,但它有点过时了(我相信现在有更多的模型;我认为也有一些不同的默认值)。你可以在这里找到它。
我将在我的示例中使用ranger
。 在ranger
模型中:
n_estimators
相当于num.trees
max_depth
相当于max.depth
此外,当方法设置为ranger
时,可以将?ranger::ranger
帮助中显示的所有参数添加到train()
中
运行此代码时,无需调用库
ranger
,但必须安装包。
从一些数据和数据准备开始(任意选择)。
library(tidyverse)
library(caret)
data("midwest")
midwest <- midwest[, c(3:6, 17:20, 27)] %>%
mutate(state = factor(state), inmetro = factor(inmetro))
现在,我将拆分数据以分离 70/30 的验证集。
# by setting a char/factor field, it's automatically stratified
set.seed(35)
tr <- createDataPartition(midwest$state, p = .7, list = F)
我将向您展示如何使用modelLookup
来查找要使用的模型。例如,如果您想查看哪些模型使用了包含单词"深度"的参数。(模型可以是基于决策树的、神经网络或任何其他类型的模型;假设从来都不安全!)
modelLookup() %>%
filter(str_detect(parameter, "depth"))
# model parameter label forReg forClass probModel
# 1 ada maxdepth Max Tree Depth FALSE TRUE TRUE
# 2 AdaBag maxdepth Max Tree Depth FALSE TRUE TRUE
# 3 AdaBoost.M1 maxdepth Max Tree Depth FALSE TRUE TRUE
# 4 blackboost maxdepth Max Tree Depth TRUE TRUE TRUE
# 5 bstTree maxdepth Max Tree Depth TRUE TRUE FALSE
# 6 ctree2 maxdepth Max Tree Depth TRUE TRUE TRUE
# 7 deepboost tree_depth Tree Depth FALSE TRUE FALSE
# 8 gbm interaction.depth Max Tree Depth TRUE TRUE TRUE
# 9 gbm_h2o max_depth Max Tree Depth TRUE TRUE TRUE
# 10 pre maxdepth Max Tree Depth TRUE TRUE TRUE
# 11 rFerns depth Fern Depth FALSE TRUE FALSE
# 12 rfRules maxdepth Maximum Rule Depth TRUE TRUE FALSE
# 13 rpart2 maxdepth Max Tree Depth TRUE TRUE TRUE
# 14 xgbDART max_depth Max Tree Depth TRUE TRUE TRUE
# 15 xgbTree max_depth Max Tree Depth TRUE TRUE TRUE
# forReg means for regression; forClass means for classification; prob means probability
正如我所说,我将使用ranger
.
modelLookup("ranger")
# model parameter label forReg forClass probModel
# 1 ranger mtry #Randomly Selected Predictors TRUE TRUE TRUE
# 2 ranger splitrule Splitting Rule TRUE TRUE TRUE
# 3 ranger min.node.size Minimal Node Size TRUE TRUE TRUE
使用此信息,我可以创建我的调优网格。
tG <- expand.grid(mtry = c(3, 4, 6), # variables to split
splitrule = c("extratrees", "variance"), # model training btw splits
min.node.size = c(3, 5, 7)) # min qty obs at each node
我将设置重复的交叉验证。
# establish how to train
tC <- trainControl(method = "repeatedcv", repeats = 5)
是时候训练模型了。我想指出的是,我在train
中记录参数的方式部分与train
函数记录的内容有关,但参数
# using formula (that's tilde period comma to say 'and everything else')
set.seed(35)
fit <- train(poptotal~.,
data = midwest[tr, ], tuneGrid = tG, trControl = tC,
method = "ranger", importance = "permutation",
scale.permutation.importance = T)
# Random Forest
#
# 309 samples
# 8 predictor
#
# No pre-processing
# Resampling: Cross-Validated (10 fold, repeated 5 times)
# Summary of sample sizes: 281, 278, 277, 277, 277, 278, ...
# Resampling results across tuning parameters:
#
# mtry splitrule min.node.size RMSE Rsquared MAE
# 3 extratrees 3 97994.57 0.9540533 23562.39
# 3 extratrees 5 99066.61 0.9523176 24111.05
# 3 extratrees 7 99757.54 0.9495842 24535.54
# 3 variance 3 114908.64 0.8855597 28326.62
# 3 variance 5 116839.06 0.8762747 28883.57
# 3 variance 7 116378.17 0.8766985 29118.59
# 4 extratrees 3 92825.54 0.9693964 20950.30
# 4 extratrees 5 93879.65 0.9677459 21342.85
# 4 extratrees 7 94963.99 0.9653268 21856.72
# 4 variance 3 108533.52 0.9188248 25262.68
# 4 variance 5 111004.38 0.9047721 26059.75
# 4 variance 7 111046.46 0.9068934 26089.53
# 6 extratrees 3 89392.68 0.9779004 18832.46
# 6 extratrees 5 90215.15 0.9764424 19059.87
# 6 extratrees 7 91033.46 0.9753090 19408.73
# 6 variance 3 101022.50 0.9531625 21934.87
# 6 variance 5 100856.81 0.9541640 21965.35
# 6 variance 7 102664.47 0.9506119 22347.86
#
# RMSE was used to select the optimal model using the smallest value.
# The final values used for the model were mtry = 6, splitrule = extratrees and min.node.size = 3.
我可以在没有所有额外信息的情况下对此模型的性能进行排队,查看 Ranger 如何对结果进行评分,并查看验证集上的预测。
p.tr <- predict.train(fit) # collect predicted values
postResample(p.tr, midwest[tr, ]$poptotal) # calculate metrics
# RMSE Rsquared MAE
# 9.928424e+04 9.710269e-01 7.736478e+03
fit$finalModel # DRASTICALLY different; these metrics are based on OOB!
# validation data
p.ts <- predict(fit, midwest[-tr, ]) # collect predicted values
postResample(p.ts, midwest[-tr, ]$poptotal) # calculate metrics
# RMSE Rsquared MAE
# 5.844063e+04 9.528124e-01 1.561766e+04
----其他解释----
围绕函数的其他解释以及它们与 Python 等效项的关系。
createDataPartitition
与train_test_split
如我的示例所示使用createDataPartition
时,它将返回将为训练样本保留的行索引值列表。它不返回四个单独的列表或向量,只返回一个。(不像train_test_split
)
我用于createDataPartion
的参数是数据向量,分区百分比,并且我想要一个向量,而不是返回的列表。
对于数据向量,最简单的方法是使用数据集的列。但是,长度与整个数据集中的行数相同的向量将执行相同的操作。
当我编写midwest[tr, ]
时,我根据createDataPartition
的输出选择了数据集中的特定行。
就您的调用而言:test_inds = createDataPartition(y
= 1:length(y)从删除不必要的内容开始)。, p = 0.2, list = F)
(
现在,如果您有一个数据框(大多数模型都需要),则没有理由在数据框中拆分X
和Y
。如果这样做,则不能将formula
用作参数。但是,如果您想完成额外的工作,则可以。如果你这样做,那么而不是formula
,你需要参数x
和y
。
使用上面的示例数据,我可以写
fitr <- train(x = midwest[tr, -3], y = midwest[tr, ]$poptotal, method = "ranger")
使用您评论中的示例,使用我示例中的相同模型,您将编写
fitr <- train(x = X_train, y = y_train, method = "ranger")
如果你有一个数据集,df1
如下所示:
# y x1 x2 x3
# 1 -1.395833 10.707157 5903.8725 0.500412
# 2 -1.955195 10.144033 1836.2500 0.501276
# 3 -2.174564 10.501878 4371.2319 0.499002
# 4 3.147530 8.838499 1783.0806 0.500391
# 5 -4.119006 7.927986 2463.0425 0.500571
# 6 -3.706576 7.608005 878.8885 0.500297
# 7 -0.525999 11.299934 3388.3888 0.497471
# 8 -0.517687 11.473103 5006.4363 0.497595
# 9 4.250880 10.151943 5366.0677 0.499125
# 10 1.530718 11.688670 3097.4672 0.500691
使用代码中的分区(其中p = .2
),设置为test_inds
,假设它返回了一个带有c(1, 2, 4, 8)
的向量
set.seed(34)
test_inds <- createDataPartition(df1$x1, p = .2, list = F)
现在当我使用时,df1[-test_inds, ]
我会删除行
# y x1 x2 x3
# 3 -2.174564 10.501878 4371.2319 0.499002
# 5 -4.119006 7.927986 2463.0425 0.500571
# 6 -3.706576 7.608005 878.8885 0.500297
# 7 -0.525999 11.299934 3388.3888 0.497471
# 9 4.250880 10.151943 5366.0677 0.499125
# 10 1.530718 11.688670 3097.4672 0.500691
如果我想像你一样拆分它,我可以。
X_train <- df1[-test_inds, -1]
Y_train <- df1[-test_inds, 1]
创建Y_train
的另一种方法:
Y_train <- df1[-test_inds, ]$y # same as other Y_train, different way of coding
这些train
函数调用是相同的。
fit <- train(y~., data = df1[-test_inds, ])
fit1 <- train(y ~ . , data = df1[-test_inds, ])
fit2 <- train(y~., data = df1, subset = -test_inds)
fit3 <- train(y ~ x1 + x2 + x3, data = df1[-test_inds, ])
fit4 <- train(x = df1[-test_inds, -1], y = df1[-test_inds, 1])
fit5 <- train(x = df1[ , -1], y = df1$y, subset = -test_inds)
fit6 <- train(x = df1[ , -1], y = df1[ , 1], subset = -test_inds)
fit7 <- train(x = X_train, y = Y_train)
如果要测试这些,下面是重新创建df1
的代码
df1 <- structure(list(
y = c(-1.395833, -1.955195, -2.174564, 3.14753, -4.119006,
-3.706576, -0.525999, -0.517687, 4.25088, 1.530718),
x1 = c(10.707157, 10.144033, 10.501878, 8.838499, 7.927986,
7.608005, 11.299934, 11.473103, 10.151943, 11.68867),
x2 = c(5903.872547, 1836.24996, 4371.231904, 1783.080566, 2463.042469,
878.888451, 3388.388772, 5006.436295, 5366.067723, 3097.467151),
x3 = c(0.500412, 0.501276, 0.499002, 0.500391, 0.500571,
0.500297, 0.497471, 0.497595, 0.499125, 0.500691)),
class = "data.frame", row.names = c(NA, -10L))
测试时,必须在每个模型之间设置种子。如果将方法设置为ranger
,则可以在train
中使用seed
中的参数。
例如:
fit <- train(y~., data = df1[-test_inds, ], method = "ranger", seed = 35)
或
set.seed(35)
fit <- train(y~., data = df1[-test_inds, ])
或
set.seed(35)
fit <- train(y~., data = df1[-test_inds, ])
set.seed(35)
fit1 <- train(y ~ . , data = df1[-test_inds, ])
set.seed(35)
fit2 <- train(y~., data = df1, subset = -test_inds)
set.seed(35)
fit3 <- train(y ~ x1 + x2 + x3, data = df1[-test_inds, ])
set.seed(35)
fit4 <- train(x = df1[-test_inds, -1], y = df1[-test_inds, 1])
set.seed(35)
fit5 <- train(x = df1[ , -1], y = df1$y, subset = -test_inds)
set.seed(35)
fit6 <- train(x = df1[ , -1], y = df1[ , 1], subset = -test_inds)
set.seed(35)
fit7 <- train(x = X_train, y = Y_train)
fit$results
# mtry RMSE Rsquared MAE RMSESD RsquaredSD MAESD
# 1 2 3.637085 0.8258667 3.413510 1.326739 0.3020918 1.274708
# 2 3 3.730395 0.8297140 3.481763 1.378773 0.2605953 1.345170
fit1$results
# mtry RMSE Rsquared MAE RMSESD RsquaredSD MAESD
# 1 2 3.637085 0.8258667 3.413510 1.326739 0.3020918 1.274708
# 2 3 3.730395 0.8297140 3.481763 1.378773 0.2605953 1.345170
fit2$results
# mtry RMSE Rsquared MAE RMSESD RsquaredSD MAESD
# 1 2 3.637085 0.8258667 3.413510 1.326739 0.3020918 1.274708
# 2 3 3.730395 0.8297140 3.481763 1.378773 0.2605953 1.345170
fit3$results
# mtry RMSE Rsquared MAE RMSESD RsquaredSD MAESD
# 1 2 3.637085 0.8258667 3.413510 1.326739 0.3020918 1.274708
# 2 3 3.730395 0.8297140 3.481763 1.378773 0.2605953 1.345170
fit4$results
# mtry RMSE Rsquared MAE RMSESD RsquaredSD MAESD
# 1 2 3.637085 0.8258667 3.413510 1.326739 0.3020918 1.274708
# 2 3 3.730395 0.8297140 3.481763 1.378773 0.2605953 1.345170
如果你不使用参数method
,默认值是method = "rf"
,这与method = "ranger"
不同,所以它们不会等价。