【超参数研究02】使用随机搜索优化超参数

【超参数研究02】使用随机搜索优化超参数_第1张图片

 一、说明

        在神经网络训练中,超参数也是需要优化的,然而在超参数较多(大于3个)后,如果用穷举的,或是通过经验约摸实现就显得费时费力,无论如何,这是需要研究、规范、整合的要点,本文对超参的随机性搜索展开研究。

二、超参数研究

       我在之前的超参数调优文章中提到了网格搜索。让我们从上次中断的地方继续。

        虽然网格搜索是用于超参数优化的强大工具,但它的计算成本可能很高,并且用于高维超参数空间不切实际。因为它使用参数网格的所有组合子集。

        随机搜索解决了这个问题。在随机搜索CV中,用户为模型的每个超参数定义值的分布。然后,该算法从这些分布中随机采样超参数,以创建一组超参数组合。例如,如果有三个范围为 [0.1、1.0]、[10, 100] 和 [1, 10] 的超参数,则算法可能会分别随机采样 0.4、75 和 5 的值,以创建超参数组合。

        当超参数的数量很大时,随机搜索比网格搜索更有效,因为它不需要评估超参数值的所有可能组合。通过随机采样超参数组合,随机搜索可以覆盖超参数空间的更广泛区域,有可能在比网格搜索更少的迭代中找到更好的超参数值。

【超参数研究02】使用随机搜索优化超参数_第2张图片

        在下一节中,我将使用网格搜索示例中使用的相同笔记本电脑价格数据集。我不会再次讨论预处理代码,但您可以参考上一篇文章以获取更多信息。一旦数据集经过了一些预处理,我们最终得到了两个数组,X 和 y,我们将使用它来构建我们的模型。

from sklearn.model_selection import RandomizedSearchCV

三、随机搜索原理应用 

        现在,让我们仔细看看课堂。它接受的参数如下:RandomizedSearchCV

  • estimator是将用于训练的模型(或管道对象)。
  • param_distributions是一个字典或字典列表,用于指定要从中采样超参数的分布。列表中的每个字典对应于一个超参数,其中键是超参数的名称,值是要从中采样的分布。rvs分布必须提供一种采样方法(例如来自scipy.stats.distributions的采样方法)。
  • n_iter是随机组合的数量。
  • cv指定交叉验证拆分策略。它可以是用于指定折叠数的整数值,也可以是交叉验证生成器,可用于定义更高级的交叉验证策略。
  • scoring是用于评估模型性能的指标。它可以采用许多不同的形式,包括字符串、可调用函数和多个指标的字典。分类指标:准确性、精度、召回率、f1。回归指标:neg_mean_squared_error,r2。聚类指标:adjusted_rand_score、silhoutte_score。这些是最受欢迎的,请访问此处查看整个列表。
  • refit指定是否使用搜索期间找到的最佳超参数重新调整整个数据集上的最佳估计器。默认情况下,设置为 ,这意味着在随机搜索完成后,对象将使用找到的最佳超参数自动重新调整整个数据集上的最佳估计器。refitTrueRandomizedSearchCV
  • verbose控制搜索期间输出的详细程度。
  • pre_dispatch用于控制网格搜索期间并行启动的作业数。它采用一个整数值,该值指定在任何给定时间可以启动的最大作业数。例如,如果 ,则在任何给定时间并行启动的作业都不会超过 2 个。pre_dispatch=2
  • random_state是种子。
  • error_score用于指定在超参数组合无法完成拟合过程时应为其分配的分数。在网格搜索过程中,该算法会针对每个超参数组合训练和评估模型。但是,有时由于内存不足或数值不稳定等原因,模型可能无法拟合或评分。在这种情况下,算法需要为失败的超参数组合分配分数,以便它可以继续搜索。RandomizedSearchCVRandomizedSearchCV
  • return_train_score指定是否在输出中包含训练分数。
import xgboost as xgb
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import uniform, randint

param_distributions = {
    'learning_rate': uniform(0.01, 0.5),
    'n_estimators': randint(100, 1000),
    'max_depth': randint(1, 10),
    'colsample_bytree': uniform(0.1, 0.9),
    'gamma': uniform(0, 1),
    'reg_alpha': uniform(0, 1),
    'reg_lambda': uniform(0, 1)
}

model = xgb.XGBRegressor(random_state=1)

# run the search
random_search = RandomizedSearchCV(
    estimator=model,
    param_distributions=param_distributions,
    n_iter=100,
    cv=5,
    random_state=42,
    verbose=1,
    scoring="neg_root_mean_squared_error"
)
random_search.fit(X_train, y_train)

"""
Fitting 5 folds for each of 100 candidates, totalling 500 fits
"""

        在此示例中,我们使用库和从库中定义一组超参数分布。uniformrandintscipy.stats

        该对象正在执行 5 倍交叉验证(即,将数据集分成 5 个相等的部分,并依次对这些部分中的每一个进行训练和评估)。对于 100 个随机生成的超参数组合中的每一个,模型将被训练和评估 5 次(数据的每一折一次)。因此,总共将有 500 个模型拟合(即,100 个超参数组合 x 每个组合 5 个折叠 = 500 个拟合)。RandomizedSearchCV

该对象与我在上一篇文章中解释的对象共享相同的属性。因此,我不会在这里再次讨论它们。您可以参考我之前的帖子以获取有关这些属性的更多信息。RandomizedSearchCVGridSearchCV

print("Best estimator: ", random_search.best_estimator_)

"""
Best estimator:  XGBRegressor(base_score=0.5, booster='gbtree', callbacks=None,
             colsample_bylevel=1, colsample_bynode=1,
             colsample_bytree=0.36664615513367416, early_stopping_rounds=None,
             enable_categorical=False, eval_metric=None,
             gamma=0.1652669390630025, gpu_id=-1, grow_policy='depthwise',
             importance_type=None, interaction_constraints='',
             learning_rate=0.017818203370596968, max_bin=256,
             max_cat_to_onehot=4, max_delta_step=0, max_depth=9, max_leaves=0,
             min_child_weight=1, missing=nan, monotone_constraints='()',
             n_estimators=443, n_jobs=0, num_parallel_tree=1, predictor='auto',
             random_state=1, reg_alpha=0.3948815181755697,
             reg_lambda=0.2934881747180381, ...)
"""
print("Best score: ", random_search.best_score_)
print("Best hyperparameters: ", random_search.best_params_)

"""
Best score:  -21681.389784324936
Best hyperparameters:  {'colsample_bytree': 0.36664615513367416, 'gamma': 0.1652669390630025, 'learning_rate': 0.017818203370596968, 'max_depth': 9, 'n_estimators': 443, 'reg_alpha': 0.3948815181755697, 'reg_lambda': 0.2934881747180381}
"""
results_df = pd.DataFrame(random_search.cv_results_)
results_df.head()

【超参数研究02】使用随机搜索优化超参数_第3张图片

        第一排result_df。图片由作者提供。

print("Best index: ", random_search.best_index_)
print("Best scorer: ", random_search.scorer_)
print("Best n splits: ", random_search.n_splits_)
print("Best refit time: ", random_search.refit_time_)
print("Best multi metric: ", random_search.multimetric_)
print("Best n features: ", random_search.n_features_in_)

"""
Best index:  10
Best scorer:  make_scorer(mean_squared_error, greater_is_better=False, squared=False)
Best n splits:  5
Best refit time:  0.45199108123779297
Best multi metric:  False
Best n features:  51
"""
best_model = random_search.best_estimator_
best_model.fit(X_train, y_train)
y_pred = best_model.predict(X_test)
rmse_train = np.sqrt(mean_squared_error(y_train, best_model.predict(X_train)))
rmse_test = np.sqrt(mean_squared_error(y_test, y_pred))
print(f"Train RMSE: {rmse_train}, Test RMSE: {rmse_test}")

"""
Train RMSE: 3604.8162519843863, Test RMSE: 17321.86440339491
"""

        我们得到的结果或多或少与.GridSearchCV

  • 当超参数的搜索空间较大,且不同超参数的值之间没有明显的相关性时,随机搜索效果最好。另一方面,网格搜索在搜索空间较小且具有清晰结构或网格状结构时效果最佳。
  • 当要搜索的超参数数量很大时,随机搜索可能比网格搜索更快,因为它只需要评估超参数的随机子集,而网格搜索评估超参数的每个组合。但是,如果搜索空间较小或要搜索的超参数数量相对较少,则网格搜索可能会更快。
  • 如果您对哪些超参数对您的模型更重要有先验知识或直觉,则网格搜索可以更有效,因为它会评估超参数的每个组合。在这种情况下,随机搜索可能不那么有效,因为它只是随机采样超参数的子集。
  • 如果计算资源有限,随机搜索可能是更好的选择,因为与网格搜索相比,它需要的资源更少。

四、阅读更多

本系列教程研究。包含:【超参数研究01】使用网格搜索优化超参数-CSDN博客

你可能感兴趣的:(机器学习原理和实现,人工智能,1024程序员节,人工智能,机器学习)