调参-网格搜索(Grid Search)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调参-网格搜索(Grid Search)相关的知识,希望对你有一定的参考价值。

参考技术A https://www.jianshu.com/p/55b9f2ea283b

原始数据集划分成训练集和测试集以后,其中测试集除了用作调整参数,也用来测量模型的好坏;这样做导致最终的评分结果比实际效果要好。(因为测试集在调参过程中,送到了模型里,而我们的目的是将训练模型应用在unseen data上)

对训练集再进行一次划分,分成训练集和验证集,这样划分的结果就是:原始数据划分为3份,分别为:训练集、验证集和测试集;其中训练集用来模型训练,验证集用来调整参数,而测试集用来衡量模型表现好坏。

交叉验证经常与网格搜索进行结合,作为参数评价的一种方法,这种方法叫做grid search with cross validation。sklearn因此设计了一个这样的类GridSearchCV,这个类实现了fit,predict,score等方法,被当做了一个estimator,使用fit方法,该过程中:(1)搜索到最佳参数;(2)实例化了一个最佳参数的estimator;

Grid Search 调参方法存在的共性弊端就是:耗时;参数越多,候选值越多,耗费时间越长。所以,一般情况下,先定一个大范围,然后再细化。

Sklearn超参调优手段:网格搜索(Grid Search)和随机搜索(Randomized Search)

超参调优是“模型调优”(Model Tuning)阶段最主要的工作,是直接影响模型最终效果的关键步骤,然而,超参调优本身却是一项非常低级且枯燥的工作,因为它的策略就是:不断变换参数值,一轮一轮地去“试”,直到找出结果最好的一组参数。显然,这个过程是可以通过编程封装成自动化的工作,而不是靠蛮力手动去一遍一遍的测试。为此,Sklearn提供了多种(自动化)超参调优方法(官方文档),其中网格搜索(Grid Search)和随机搜索(Randomized Search)是最基础也是最常用的两个:

方法名称对应类/函数官方文档
网格搜索(Grid Search)sklearn.model_selection.GridSearchCV文档链接
随机搜索(Randomized Search)sklearn.model_selection.RandomizedSearchCV文档链接

对应类/函数的后缀CV是Cross-Validation的意思,因为它们每尝试一种超参组合时,都会使用Cross-Validation进行效果评估,所以调用它们时也都需要显式指定cv参数,即:验证的轮次(K-Fold的份数)。

网格搜索(Grid Search)

网格搜索(Grid Search)的逻辑其实非常简单,就是由开发者针对每个超参设定多个值去尝试,找出效果最好的那个,由于超参会有很多个,而每一个超参又有多个尝试值,所以就变成了一个“排列组合”问题。例如我们想针对两个超参进行调优,第一个超参设置了2个尝试值,第二个超参设置了3个尝试值,则超参设置总共会有 2 × 3 = 6 种组合,理论上模型要被训练6次,如果再加上交叉验证的轮次参数cv,假设cv=3,则总得的训练次数将变为:6 × 3 = 18 次。以下是《Hands-On ML, 2nd Edition》一书中提供的GridSearchCV示例代码:

from sklearn.model_selection import GridSearchCV
param_grid = [
    'n_estimators': [3, 10, 30], 'max_features': [2, 4, 6, 8],
    'bootstrap': [False], 'n_estimators': [3, 10], 'max_features': [2, 3, 4],
]
forest_reg = RandomForestRegressor()
grid_search = GridSearchCV(forest_reg, param_grid, cv=5,
                           scoring='neg_mean_squared_error',
                           return_train_score=True)
grid_search.fit(housing_prepared, housing_labels)

在这份示例代码中,作者提供针对bootstrap、n_estimators和max_features三个超参,给出了两套参数设定:

  • 第一套:'n_estimators': [3, 10, 30], 'max_features': [2, 4, 6, 8] 总计:3 × 4 = 12 种组合
  • 第二套:'bootstrap': [False], 'n_estimators': [3, 10], 'max_features': [2, 3, 4] 总计:1 × 2 × 3 = 6 种组合

合在一起一共:12 + 6 = 18 种组合,加上交叉验证设定cv=5,所以最终将训练 18 × 5 = 90 次!这里我们可以看到param_grid是一个list,里面每一个元素是一个dict,一个dict就代表了一套参数设定,每套参数设定根据赋值情况又会产生多种参数组合。其实上面两套组合也可以用下面的一套设定覆盖:

param_grid = [
    'bootstrap': [True, False], 'n_estimators': [3, 10, 30], 'max_features': [2, 3, 4, 6, 8]
]

但在此情况下,总的训练次数将会变为:(2 × 3 × 5) × 5 = 150 次。由此可见,Sklearn这种允许设定多套参数的设计(即一个list下可配置多个dict)还是有可取之处,会方便开发人员更具经验设定最有希望的取值集合,减少训练次数。

随机搜索(Randomized Search)

网格搜索适用于参数组合数比较少的情况,当参数组合大到一定程度后,模型训练所占用的资源和持续时间将会超用户的可接受范围,此时往往就要改用随机搜索(Randomized Search)了。随机搜索的工作原理和网格搜索其实差不多,都是“暴力尝试”,不同之处在于:网格搜索的参数取值集合是用户设定的,而随机搜索的参数取值则是指定好区间(最大值和最小值)由随机数发生器随机生成的,而想要生成多少种组合是可以设置的。以下是《Hands-On ML, 2nd Edition》一书中提供的RandomizedSearchCV示例代码:

from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint

param_distribs = 
        'n_estimators': randint(low=1, high=200),
        'max_features': randint(low=1, high=8),
    

forest_reg = RandomForestRegressor(random_state=42)
rnd_search = RandomizedSearchCV(forest_reg, param_distributions=param_distribs,
                                n_iter=10, cv=5, scoring='neg_mean_squared_error', random_state=42)
rnd_search.fit(housing_prepared, housing_labels)

在这份代码中,作者针对n_estimators和max_features两个超参分别设定了 1 ~ 200 和 1 ~ 8 的取值区间,然后通过设定参数n_iter=10将参数组合数设定为10,当然,叠加上交叉验证cv=5后,实际的训练就是 5 × 10 = 50 次了。

以上是关于调参-网格搜索(Grid Search)的主要内容,如果未能解决你的问题,请参考以下文章

Sklearn超参调优手段:网格搜索(Grid Search)和随机搜索(Randomized Search)

Sklearn超参调优手段:网格搜索(Grid Search)和随机搜索(Randomized Search)

使用网格搜索调整模型

调参必备---GridSearch网格搜索

Lesson 9.3 集成算法的参数空间与网格优化和使用网格搜索在随机森林上进行调参

XGBoost模型调参:GridSearchCV方法网格搜索优化参数