1.什么是超参数

超参数(hyper parameters)就是机器学习或深度学习算法中需要预先设置的参数,这些参数不是通过训练数据学习到的参数;原始算法一般只给出超参数的取值范围和含义,根据不同的应用场景,同一个算法的同一超参数设置也不同。

那超参数应该如何设置呢?似乎没有捷径,去尝试不同的取值,比较不同的结果取最好的结果。

本文整理了不同的尝试方法,如下:

  • RandomSearch

  • GridSearch

  • 贝叶斯优化(Bayesian optimization)

2. GridSearchCV

暴力穷举是寻找最优超参数一种简单有效的方法,但是对于算法庞大的超参数空间来说,穷举会损耗大量的时间,特别是多个超参数情况下。GridSearchCV的做法是缩减了超参数值的空间,只搜索人为重要的超参数和有限的固定值。同时结合了交叉验证的方式来搜索最优的超参数。

拿lightgbm为例子:

import pandas as pd
import numpy as np
import math
import warnings
import lightgbm as lgb
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import RandomizedSearchCVlg = lgb.LGBMClassifier(silent=False)
param_dist = {"max_depth": [2, 3, 4, 5, 7, 10],"n_estimators": [50, 100, 150, 200],"min_child_samples": [2,3,4,5,6]}grid_search = GridSearchCV(estimator=lg, n_jobs=10, param_grid=param_dist, cv = 5, scoring='f1', verbose=5)
grid_search.fit(X_train, y)
grid_search.best_estimator_, grid_search.best_score_# Fitting 5 folds for each of 120 candidates, totalling 600 fits
# [Parallel(n_jobs=10)]: Using backend LokyBackend with 10 concurrent workers.
# [Parallel(n_jobs=10)]: Done  52 tasks      | elapsed:    2.5s
# [Parallel(n_jobs=10)]: Done 142 tasks      | elapsed:    6.6s
# [Parallel(n_jobs=10)]: Done 268 tasks      | elapsed:   14.0s
# [Parallel(n_jobs=10)]: Done 430 tasks      | elapsed:   25.5s
# [Parallel(n_jobs=10)]: Done 600 out of 600 | elapsed:   40.6s finished
# (LGBMClassifier(max_depth=10, min_child_samples=6, n_estimators=200,
#                 silent=False), 0.6359524127649383)

从上面可知,GridSearchCV搜索过程

  • 模型estimator:lgb.LGBMClassifier

  • param_grid:模型的超参数,上面例子给出了3个参数,值得数量分别是6,4,5,组合起来的搜索空间是120个

  • cv:交叉验证的折数(上面例子5折交叉), 算法训练的次数总共为120*5=600

  • scoring:模型好坏的评价指标分数,如F1值

  • 搜索返回: 最好的模型 best_estimator_和最好的分数

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html#sklearn.model_selection.GridSearchCV

3. RandomSearchCV

GridSearchCV一样,RandomSearchCV也是在有限的超参数空间(人为重要的超参数)中搜索最优超参数。不一样的地方在于搜索超参数的值不是固定,是在一定范围内随机的值。不同超参数值的组合也是随机的。值的随机性可能会弥补GridSearchCV超参数值固定的有限组合,但也可能更坏。

Better than grid search in various senses but still expensive to guarantee good coverage

import pandas as pd
import numpy as np
import math
import warnings
import lightgbm as lgb
from scipy.stats import uniform
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import RandomizedSearchCVlg = lgb.LGBMClassifier(silent=False)
param_dist = {"max_depth": range(2,15,1),"n_estimators": range(50,200,4),"min_child_samples": [2,3,4,5,6],}random_search = RandomizedSearchCV(estimator=lg, n_jobs=10, param_distributions=param_dist, n_iter=100, cv = 5, scoring='f1', verbose=5)
random_search.fit(X_train, y)
random_search.best_estimator_, random_search.best_score_# Fitting 5 folds for each of 100 candidates, totalling 500 fits
# [Parallel(n_jobs=10)]: Using backend LokyBackend with 10 concurrent workers.
# [Parallel(n_jobs=10)]: Done  52 tasks      | elapsed:    6.6s
# [Parallel(n_jobs=10)]: Done 142 tasks      | elapsed:   12.9s
# [Parallel(n_jobs=10)]: Done 268 tasks      | elapsed:   22.9s
# [Parallel(n_jobs=10)]: Done 430 tasks      | elapsed:   36.2s
# [Parallel(n_jobs=10)]: Done 500 out of 500 | elapsed:   42.0s finished
# (LGBMClassifier(max_depth=11, min_child_samples=3, n_estimators=198,
#                 silent=False), 0.628180299445963)

从上可知,基本和GridSearchCV类似,不同之处如下:

  • n_iter:随机搜索值的数量

  • param_distributions:搜索值的范围,除了list之外,也可以是某种分布如uniform均匀分布等

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RandomizedSearchCV.html#sklearn.model_selection.RandomizedSearchCV

4. 贝叶斯优化(Bayesian optimization)

不管是GridSearchCV还是RandomSearchCV, 都是在调参者给定的有限范围内搜索全部或者部分参数的组合情况下模型的最佳表现;可想而知最优模型参数取决于先验的模型参数和有限范围,某些情况下并一定是最优的, 而且暴力搜索对于大的候选参数空间也是很耗时的。

我们换了角度来看待参数搜索的问题:我们的目的是选择一个最优的参数组合,使得训练的模型在给定的数据集上表现最好,所以可以理解成是一个最优化问题。

我们通常使用梯度下降的方式来迭代的计算最优值,但是梯度下降要求优化的函数是固定并且是可导的,如交叉熵loss等。对于参数搜索问题, 我们要在众多模型(不同的超参)中找一个效果最好的模型,判断是否最好是由模型决定的,而模型是一个黑盒子,不知道是什么结构,以及是否是凸函数,是没办法使用梯度下降方法。

这种情况下,贝叶斯优化是一种解决方案。贝叶斯优化把搜索的模型空间假设为高斯分布,利用高斯过程,按迭代的方式每次计算得到比当前最优参数期望提升的新的最优参数。

通用的算法如下:

  • Input:f是模型, M是高斯拟合函数, X是参数, S是参数选择算法Acquisition Function

  • 初始化高斯分布拟合的数据集D,为(x,y), x是超参数,y是超参数的x的执行结果(如精确率等)

  • 迭代T次

  • 每次迭代,用D数据集拟合高斯分布函数

  • 根据拟合的函数,根据Acquisition Function(如Expected improvement算法),在参数空间选择一个比当前最优解更优的参数xi

  • 将参数xi代入模型f(训练一个模型),得出相应的yi(新模型的精确率等)

  • (xi,yi)重新加入拟合数据集D,再一次迭代

由此可知,贝叶斯优化每次都利用上一次参数选择。而GridSearchCVRandomSearchCV每一次搜索都是独立的。

到此,简单介绍了贝叶斯优化的理论知识。有很多第三方库实现了贝叶斯优化的实现,如 advisorbayesian-optimizationScikit-OptimizeGPyOpt等。本文以GPyOptbayesian-optimization为例子。

pip install gpyopt
pip install bayesian-optimization
pip install scikit-optimize
  • gpyopt例子

import GPy
import GPyOpt
from GPyOpt.methods import BayesianOptimization
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris
from xgboost import XGBRegressor
import numpy as npiris = load_iris()
X = iris.data
y = iris.targetx_train, x_test, y_train, y_test = train_test_split(X,y,test_size = 0.3,random_state = 14)# 超参数搜索空间
bds = [{'name': 'learning_rate', 'type': 'continuous', 'domain': (0, 1)},{'name': 'gamma', 'type': 'continuous', 'domain': (0, 5)},{'name': 'max_depth', 'type': 'continuous', 'domain': (1, 50)}]# Optimization objective 模型F
def cv_score(parameters):parameters = parameters[0]score = cross_val_score(XGBRegressor(learning_rate=parameters[0],gamma=int(parameters[1]),max_depth=int(parameters[2])), X, y, scoring='neg_mean_squared_error').mean()score = np.array(score)return score# acquisition就是选择不同的Acquisition Function
optimizer = GPyOpt.methods.BayesianOptimization(f = cv_score,            # function to optimize       domain = bds,         # box-constraints of the problemacquisition_type ='LCB',       # LCB acquisitionacquisition_weight = 0.1)   # Exploration exploitationx_best = optimizer.X[np.argmax(optimizer.Y)]
print("Best parameters: learning_rate="+str(x_best[0])+",gamma="+str(x_best[1])+",max_depth="+str(x_best[2]))
# Best parameters: learning_rate=0.4272184438229706,gamma=1.4805727469635759,max_depth=41.8460390442754
  • bayesian-optimization例子

from sklearn.datasets import make_classification
from xgboost import XGBRegressor
from sklearn.model_selection import cross_val_score
from bayes_opt import BayesianOptimizationiris = load_iris()
X = iris.data
y = iris.targetx_train, x_test, y_train, y_test = train_test_split(X,y,test_size = 0.3,random_state = 14)
bds ={'learning_rate': (0, 1),'gamma': (0, 5),'max_depth': (1, 50)}# Optimization objective
def cv_score(learning_rate, gamma,  max_depth):score = cross_val_score(XGBRegressor(learning_rate=learning_rate,gamma=int(gamma),max_depth=int(max_depth)), X, y, scoring='neg_mean_squared_error').mean()score = np.array(score)return scorerf_bo = BayesianOptimization(cv_score,bds)
rf_bo.maximize()
rf_bo.max |   iter    |  target   |   gamma   | learni... | max_depth |
-------------------------------------------------------------
|  1        | -0.0907   |  0.7711   |  0.1819   |  20.33    |
|  2        | -0.1339   |  4.933    |  0.6599   |  8.972    |
|  3        | -0.07285  |  1.55     |  0.8247   |  33.94    |
|  4        | -0.1359   |  4.009    |  0.3994   |  25.55    |
|  5        | -0.08773  |  1.666    |  0.9551   |  48.67    |
|  6        | -0.05654  |  0.0398   |  0.3707   |  1.221    |
|  7        | -0.08425  |  0.6883   |  0.2564   |  33.25    |
|  8        | -0.1113   |  3.071    |  0.8913   |  1.051    |
|  9        | -0.9167   |  0.0      |  0.0      |  2.701    |
|  10       | -0.05267  |  0.0538   |  0.1293   |  1.32     |
|  11       | -0.08506  |  1.617    |  1.0      |  32.68    |
|  12       | -0.09036  |  2.483    |  0.2906   |  33.21    |
|  13       | -0.08969  |  0.4662   |  0.3612   |  34.74    |
|  14       | -0.0723   |  1.295    |  0.2061   |  1.043    |
|  15       | -0.07531  |  1.903    |  0.1182   |  35.11    |
|  16       | -0.08494  |  2.977    |  1.0      |  34.57    |
|  17       | -0.08506  |  1.231    |  1.0      |  36.05    |
|  18       | -0.07023  |  2.81     |  0.838    |  36.16    |
|  19       | -0.9167   |  1.94     |  0.0      |  36.99    |
|  20       | -0.09041  |  3.894    |  0.9442   |  35.52    |
|  21       | -0.1182   |  3.188    |  0.01882  |  35.14    |
|  22       | -0.08521  |  0.931    |  0.05693  |  31.66    |
|  23       | -0.1003   |  2.26     |  0.07555  |  31.78    |
|  24       | -0.1018   |  0.08563  |  0.9838   |  32.22    |
|  25       | -0.1017   |  0.8288   |  0.9947   |  30.57    |
|  26       | -0.9167   |  1.943    |  0.0      |  30.2     |
|  27       | -0.08506  |  1.518    |  1.0      |  35.04    |
|  28       | -0.08494  |  3.464    |  1.0      |  32.36    |
|  29       | -0.1224   |  4.296    |  0.4472   |  33.47    |
|  30       | -0.1017   |  0.0      |  1.0      |  35.86    |
=============================================================
{'target': -0.052665895082105285,'params': {'gamma': 0.05379782654053811,'learning_rate': 0.1292986176550608,'max_depth': 1.3198257775801387}}

bayesian-optimization只支持最大化,如果score是越小越好,可以加一个负号转化为最大值优化。

两者的优化结果并不是十分一致的,可能和实现方式和选择的算法不同,也和初始化的拟合数据集有关系。

5. 总结

本文介绍三种超参数优化的策略,希望对你有帮助。简要总结如下:

  • GridSearchCV网格搜索,给定超参和取值范围,遍历所有组合得到最优参数。首先你要给定一个先验的取值,不能取得太多,否则组合太多,耗时太长。可以启发式的尝试。

  • RandomSearchCV随机搜索,搜索超参数的值不是固定,是在一定范围内随机的值

  • 贝叶斯优化,采用高斯过程迭代式的寻找最优参数,每次迭代都是在上一次迭代基础上拟合高斯函数上,寻找比上一次迭代更优的参数,推荐gpyopt库

6. 参考资料

  • A Tutorial on Bayesian Optimization

  • https://zhuanlan.zhihu.com/p/93683454

  • https://zhuanlan.zhihu.com/p/29779000

  • https://zhuanlan.zhihu.com/p/53826787

作者简介:wedo实验君, 数据分析师;热爱生活,热爱写作

赞 赏 作 者

更多阅读

[视频]GitHub趋势榜(2021年1月第二周)

特别推荐

点击下方阅读原文加入社区会员

Python 机器学习:超参数调优相关推荐

  1. python minimize_简单三步实现Python脚本超参数调优(附代码)

    作者:Jakub Czakon, Neptune.ai 翻译:陈之炎 校对:和中华 本文约1500字,建议阅读5分钟. Python机器学习模型建立起来之后,如何对它的性能进行优化?按照本指南中的三个 ...

  2. 独家 | 简单三步实现Python脚本超参数调优(附代码)

    作者:Jakub Czakon, Neptune.ai 翻译:陈之炎 校对:和中华 本文约1500字,建议阅读5分钟. Python机器学习模型建立起来之后,如何对它的性能进行优化?按照本指南中的三个 ...

  3. 机器学习——超参数调优

    超参数是在开始学习过程之前设置值的参数,而不是通过训练得到的参数数据.超参数可以分为两种类型:定义模型及结构本身的参数,目标函数与与优化算法所需的参数,前者用于训练和预测阶段,后者用于训练阶段. 在实 ...

  4. 简单三步实现Python脚本超参数调优(附代码)

    在编写完成一个Python脚本之后,便可以用它训练和评估机器学习模型了,现在,问题来了,是否能对它自动调整超参数以提高其性能呢? 自有办法! 在本文中,将展示如何将脚本转换为可以用任何超参数优化库优化 ...

  5. 深度学习-超参数调优

    在机器学习中有很多调优的方式机器学习--超参数调优,深度学习中也存在同样的方式,接下来,介绍一下深度学习框架里边的自动调参模块. 1. 基于Tensorflow的Keras tuner 官方教程如下: ...

  6. 【进阶版】机器学习之特征降维、超参数调优及检验方法(04)

    目录 欢迎订阅本专栏,持续更新中~ 本专栏前期文章介绍! 机器学习配套资源推送 进阶版机器学习文章更新~ 点击下方下载高清版学习知识图册 线性判别分析(LDA) 主成分分析(PCA) 超参数调优 检验 ...

  7. 机器学习模型评估与超参数调优详解

    ↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习,不错过 Datawhale干货 作者:李祖贤  深圳大学,Datawhale高校群成员 机器学习分为两类 ...

  8. python代码设置超参数_超参数调优总结,贝叶斯优化Python代码示例

    本文介绍超参数(hyperparameter)的调优方法. 神经网络模型的参数可以分为两类,模型参数,在训练中通过梯度下降算法更新: 超参数,在训练中一般是固定数值或者以预设规则变化,比如批大小(ba ...

  9. 贝叶斯优化python包_《用贝叶斯优化进行超参数调优》

    TPE CMAES 网格搜索 随机搜索 贝叶斯优化 用贝叶斯优化进行超参数调优 @QI ZHANG · JUL 12, 2019 · 7 MIN READ 超参数调优一直是机器学习里比较intract ...

  10. Python的数据分析中超参数调优方法:网格搜索

    [小白从小学Python.C.Java] [Python全国计算机等级考试] [Python数据分析考试必会题] ● 标题与摘要 Python的数据分析中 超参数调优方法:网格搜索 ● 选择题 以下说 ...

最新文章

  1. 查询去除空值_SQL多表查询
  2. 浏览器卡怎么办_SD卡无法格式化怎么修复?简单修复方法介绍
  3. 你会在你的WebRTC 应用程序中使用哪种视频编解码器呢?
  4. linux内核之旅ppt_一起玩转 Linux 内核之旅开源社区吧
  5. Float Protocol将于5月7日至10日进行FLOAT代币创世发布
  6. php5.5.35安装,如何安装php5
  7. 科技四巨头展望:战线***升级 软硬界限模糊
  8. 分享C#实现XML和实体序列化和反序列化的代码
  9. 硅谷之火:人与计算机的未来
  10. Java自动化测试——打开浏览器
  11. 企业网络冗余技术(EthernetChannel、HSRP、VRRP)
  12. NetLimiter 4.0.15.0 x64 破解新鲜出炉!
  13. edge浏览器使用IE模式进行调试
  14. css/js解决 页面多次点击时出现部分蓝色
  15. 2021有效的电子邮箱号码大全,外贸企业邮箱地址大全
  16. window下搭建php环境
  17. 微信小程序调试过程中页面加载不出来
  18. 【渝粤题库】陕西师范大学201671 高级英语(二)
  19. 静态变量和静态方法编程训练—信用卡消费记录
  20. Python 实现延时队列

热门文章

  1. java 反射基础 万字详解(Class-Constructor-Method-Field一条龙)
  2. 从纸带到U盘:移动存储介质的发展史
  3. Kali linux截图软件
  4. Linux下的文件目录及其作用
  5. ARCGIS叠加分析
  6. 通信原理简明教程 | 现代数字调制
  7. springBoot报 :Address already in use: bind错误
  8. 激光雷达远距离灰尘扬尘烟雾粉尘检测
  9. C#中静态与非静态的区别
  10. 基础研究·应用研究·开发研究的区别