随机森林中的超参数调整

Posted

技术标签:

【中文标题】随机森林中的超参数调整【英文标题】:Hyperparameter Tuning in Random forest 【发布时间】:2019-05-01 20:51:27 【问题描述】:

我在 sklearn 的 RandomForestRegressor 的帮助下尝试在 Boston 数据集上使用随机森林算法来预测 medv 的房价。总之,我尝试了 3 iterations 如下

迭代 1:使用具有默认超参数的模型

#1. import the class/model
from sklearn.ensemble import RandomForestRegressor
#2. Instantiate the estimator
RFReg = RandomForestRegressor(random_state = 1, n_jobs = -1) 
#3. Fit the model with data aka model training
RFReg.fit(X_train, y_train)

#4. Predict the response for a new observation
y_pred = RFReg.predict(X_test)


y_pred_train = RFReg.predict(X_train)

迭代 1 的结果

'RMSE Test': 2.9850839211419435, 'RMSE Train': 1.2291604936401441

迭代 2:我使用RandomizedSearchCV 来获得超参数的最佳值

from sklearn.ensemble import RandomForestRegressor
RFReg = RandomForestRegressor(n_estimators = 500, random_state = 1, n_jobs = -1) 

param_grid =  
    'max_features' : ["auto", "sqrt", "log2"],
    'min_samples_split' : np.linspace(0.1, 1.0, 10),
     'max_depth' : [x for x in range(1,20)]


from sklearn.model_selection import RandomizedSearchCV
CV_rfc = RandomizedSearchCV(estimator=RFReg, param_distributions =param_grid, n_jobs = -1, cv= 10, n_iter = 50)
CV_rfc.fit(X_train, y_train)

所以我得到了最好的超参数如下

CV_rfc.best_params_
#'min_samples_split': 0.1, 'max_features': 'auto', 'max_depth': 18
CV_rfc.best_score_
#0.8021713812777814

所以我用 best 超参数训练了一个新模型,如下所示

#1. import the class/model
from sklearn.ensemble import RandomForestRegressor
#2. Instantiate the estimator
RFReg = RandomForestRegressor(n_estimators = 500, random_state = 1, n_jobs = -1, min_samples_split = 0.1, max_features = 'auto', max_depth = 18) 
#3. Fit the model with data aka model training
RFReg.fit(X_train, y_train)

#4. Predict the response for a new observation
y_pred = RFReg.predict(X_test)


y_pred_train = RFReg.predict(X_train)

迭代 2 的结果

'RMSE Test': 3.2836794902147926, 'RMSE Train': 2.71230367772569

迭代 3:我使用GridSearchCV 来获得超参数的最佳值

from sklearn.ensemble import RandomForestRegressor
RFReg = RandomForestRegressor(n_estimators = 500, random_state = 1, n_jobs = -1) 

param_grid =  
    'max_features' : ["auto", "sqrt", "log2"],
    'min_samples_split' : np.linspace(0.1, 1.0, 10),
     'max_depth' : [x for x in range(1,20)]



from sklearn.model_selection import GridSearchCV
CV_rfc = GridSearchCV(estimator=RFReg, param_grid=param_grid, cv= 10, n_jobs = -1)
CV_rfc.fit(X_train, y_train)

所以我得到了最好的超参数如下

CV_rfc.best_params_
#'max_depth': 12, 'max_features': 'auto', 'min_samples_split': 0.1
CV_rfc.best_score_
#0.8021820114800677

迭代 3 的结果

'RMSE Test': 3.283690568225705, 'RMSE Train': 2.712331014201783

我的函数来评估RMSE

def model_evaluate(y_train, y_test, y_pred, y_pred_train):
    metrics = 
    #RMSE Test
    rmse_test = np.sqrt(mean_squared_error(y_test, y_pred))
    #RMSE Train
    rmse_train = np.sqrt(mean_squared_error(y_train, y_pred_train))

    metrics = 
              'RMSE Test': rmse_test,
              'RMSE Train': rmse_train

    return metrics 

所以在 3 次迭代后我有以下问题

    即使我使用RandomSearchCVGridSearchCV,为什么tuned 模型的结果比使用默认参数的模型最差。理想情况下,通过交叉验证进行调整时,模型应该会产生良好的结果 我知道交叉验证只会针对param_grid 中存在的值的组合进行。可能存在良好但未包含在我的param_grid 中的值。那么我该如何处理这种情况 我如何决定我应该为max_featuresmin_samples_splitmax_depth 或机器学习模型中的任何超参数尝试什么值的范围,以提高其准确性.(这样我至少可以得到一个比具有默认超参数的模型更好的调整模型)

【问题讨论】:

对于您的问题 #2 和 #3,没有“硬”的科学答案(甚至是广泛的指导方针);这是艺术的一部分,来自经验(可以说你自己已经获得了一些,这可能在实践中转化为“也总是尝试默认参数”);您的问题 #1 的可能答案可能在于您的问题 #2... 【参考方案1】:

为什么调优模型的结果比默认模型差 即使我使用的是 RandomSearchCV 和 GridSearchCV 参数。 理想情况下,模型在调整时应该给出良好的结果 交叉验证

您的第二个问题回答了您的第一个问题,但我试图在波士顿数据集上重现您的结果,我得到了带有默认参数的 'test_rmse':3.987, 'train_rmse':1.442'test_rmse':3.98, 'train_rmse':3.426 用于随机搜索的“调整”参数,'test_rmse':3.993, 'train_rmse':3.481 带有网格搜索。然后我使用hyperopt 和以下参数空间

 'max_depth': hp.choice('max_depth', range(1, 100)),
    'max_features': hp.choice('max_features', range(1, x_train.shape[1])),
    'min_samples_split': hp.uniform('min_samples_split', 0.1, 1)

大约运行 200 次后,结果看起来像这样, 所以我将空间扩大到'min_samples_split', 0.01, 1,这让我得到了'test_rmse':3.278, 'train_rmse':1.716 的最佳结果,min_samples_split 等于0.01。根据文档,min_samples_split 的公式是 ceil(min_samples_split * n_samples),在我们的例子中,np.ceil(0.1 * len(x_train))=34 对于像这样的小数据集来说可能有点大。

我知道交叉验证只会针对组合进行 param_grid 中存在的值。可能有很好的值 但不包含在我的 param_grid 中。那么我该如何处理这种 情况

我如何决定我应该尝试的值范围 max_features、min_samples_split、max_depth 或任何 机器学习模型中的超参数以增加其 准确性。(这样我至少可以得到一个比 具有默认超参数的模型)

这个你不能提前知道,所以你要对每个算法做研究,看看通常搜索什么样的参数空间(这方面的好来源是kaggle,例如googlekaggle kernel random forest),合并它们,帐户为您的数据集特征并使用某种Bayesian Optimization 算法(有multiple existing libraries 用于此)对其进行优化,该算法尝试以最佳方式选择新参数值以供选择。

【讨论】:

简洁地演示了min_samples_split 如何成为比max_depth 更有用(一致)的超参数来限制深度。我猜min_samples_leaf 看起来会很相似? @jonnor 是的,min_samples_leafgraph 看起来非常相似。

以上是关于随机森林中的超参数调整的主要内容,如果未能解决你的问题,请参考以下文章

随机森林中的 tuneGrid 参数问题

#调整随机森林的参数(调整max_features,结果未见明显差异)

使用 GridSearchCV 调整 scikit-learn 的随机森林超参数

如何调整随机森林的参数达到更好的效果。

使用超网格搜索和 10 倍 CV 调整参数后,随机森林模型的 AUC 较低

如何调整随机森林模型中的特征权重?