DataWhale第23期组队集成学习上-Task4

对模型超参数进行调优(调参)

(!tips:蓝色字今天依旧是转跳惊喜)


​ 在上一次的讨论中,我们似乎对模型的优化都是对模型算法本身的改进,比如: 岭回归对线性回归的优化在于线性回归的损失函数中L2正则化项,从而牺牲无偏性降低方差

​ 但是,大家是否想过这样的问题:在L2正则化中参数 λ \lambda λ应该选择多少?是0.01、0.1、还是1?到目前为止,我们只能凭经验或者瞎猜,能不能找到一种方法找到最优的参数 λ \lambda λ

​ 事实上,找到最佳参数的问题本质上属于最优化的内容,因为从一个参数集合中找到最佳的值本身就是最优化的任务之一,我们脑海中浮现出来的算法无非就是:梯度下降法、牛顿法等无约束优化算法或者约束优化算法,但是在具体验证这个想法是否可行之前,我们必须先认识两个最本质概念的区别。

1. 参数与超参数

我们很自然的问题就是岭回归中的参数 λ \lambda λ和参数w之间有什么不一样?事实上,参数w是我们通过设定某一个具体的 λ \lambda λ后使用类似于最小二乘法、梯度下降法等方式优化出来的,我们总是设定了 λ \lambda λ是多少后才优化出来的参数w。

​ 因此,类似于参数w一样,使用最小二乘法或者梯度下降法等最优化算法优化出来的数我们称为参数,类似于 λ \lambda λ一样,我们无法使用最小二乘法或者梯度下降法等最优化算法优化出来的数我们称为超参数

​ 模型参数模型内部的配置变量,其值可以根据数据进行估计。有关参数:

  • 进行预测时需要参数。
  • 它参数定义了可使用的模型。
  • 参数是从数据估计或获悉的。
  • 参数通常不由编程者手动设置。
  • 参数通常被保存为学习模型的一部分。
  • 参数是机器学习算法的关键,它们通常由过去的训练数据中总结得出 。

​ 模型超参数模型外部的配置,是在开始学习过程之前设置值的参数,其值无法从数据中估计。通常情况下,需要对超参数进行优化,给学习机选择一组最优超参数,以提高学习的性能和效果。有关超参数:

  • 超参数通常用于帮助估计模型参数。

    • 超参数通常由人工指定。
    • 超参数通常可以使用启发式设置。
    • 超参数经常被调整为给定的预测建模问题。

超参数的一些示例

  • 数的数量或数的深度;

  • 矩阵分解中潜在因数的数量;

  • 学习率(多种模式);

  • 深层神经网络隐藏层数;

  • k均值聚类中的簇数。

    我们前面(4)部分的优化都是基于模型本身的具体形式的优化,那本次(5)调整的内容是超参数,也就是取不同的超参数的值对于模型的性能有不同的影响。

2. 网格搜索GridSearchCV()

  • 网格搜索class sklearn.model_selection.GridSearchCV(estimator, param_grid, *, scoring=None, n_jobs=None, refit=True, cv=None, verbose=0, pre_dispatch=‘2*n_jobs’, error_score=nan, return_train_score=False)

  • 网格搜索结合管道

​ 网格搜索的思想非常简单,比如你有2个超参数需要去选择,那你就把所有的超参数选择列出来分别做排列组合。举个例子: λ = 0.01 , 0.1 , 1.0 \lambda = 0.01,0.1,1.0 λ=0.01,0.1,1.0 α = 0.01 , 0.1 , 1.0 \alpha = 0.01,0.1,1.0 α=0.01,0.1,1.0,你可以做一个排列组合,即:{[0.01,0.01],[0.01,0.1],[0.01,1],[0.1,0.01],[0.1,0.1],[0.1,1.0],[1,0.01],[1,0.1],[1,1]} ,然后针对每组超参数分别建立一个模型,然后选择测试误差最小的那组超参数。换句话说,我们需要从超参数空间中寻找最优的超参数,很像一个网格中找到一个最优的节点,因此叫网格搜索

3. 随机搜索RandomizedSearchCV()

  • 随机搜索class sklearn.model_selection.RandomizedSearchCV(estimator, param_distributions, *, n_iter=10, scoring=None, n_jobs=None, refit=True, cv=None, verbose=0, pre_dispatch=‘2*n_jobs’, random_state=None, error_score=nan, return_train_score=False)

​ 网格搜索相当于暴力地从参数空间中每个都尝试一遍,然后选择最优的那组参数,这样的方法显然是不够高效的,因为随着参数类别个数的增加,需要尝试的次数呈指数级增长。有没有一种更加高效的调优方式呢?那就是使用随机搜索的方式,这种方式不仅仅高校,而且实验证明,随机搜索法结果比稀疏化网格法稍好(有时候也会极差,需要权衡)。参数的随机搜索中的每个参数都是从可能的参数值的分布中采样的,简单地对参数设置进行固定次数的随机搜索。与网格搜索相比,这有两个主要优点:

  • 可以独立于参数数量和可能的值来选择计算成本。
  • 添加不影响性能的参数不会降低效率。

4. 其他的优化方法

4.1 贝叶斯优化

​ 贝叶斯优化(BOA)利用之前已搜索点的信息确定下一个搜索点,用于求解维数不高的黑盒优化问题。

​ 它的思路是首先生成一个初始候选解集合,然后根据这些点寻找下一个有可能是极值的点,将该点加入集合中,重复这一步骤,直至迭代终止。然后从这些点中找到极值点作为问题的解。

​ 而问题的关键就是如何根据已搜索的点确定下一个搜索点。贝叶斯优化根据已经搜索的点的函数值估计真实目标函数值的均值和方差,根据均值和方差可以构造出采集函数(acquisition function),即对每一点是函数极值点的可能性的估计,反映了每一个点值得搜索的程度,该函数的极值点是下一个搜索点

​ 算法的核心由两部分构成:对目标函数进行建模,即计算每一点处的函数值的均值和方差,通常用高斯过程回归实现;构造采集函数,用于决定本次迭代时在哪个点处进行采样。

参考链接:理解贝叶斯优化

4.2 基于梯度的优化

​ 对于特定的学习算法,可以计算相对于超参数的梯度,然后使用梯度下降优化超参数。

4.2.1 批量梯度下降法BGD

​ 批量梯度下降法(BGD)是梯度下降法最原始的形式,它的具体思路是在更新每一参数时都使用所有的样本来进行更新。它得到的是一个全局最优解,但每迭代一步都要用到训练集所有的数据,如果样本数量很大,那么训练过程就会很费时。

  • 优点:全局最优解;易于并行实现;
  • 缺点:当样本数目很多时,训练过程会很慢。
4.2.2 随机梯度下降法SGD

​ 由于批量梯度下降法在更新每一个参数时,都需要所有训练样本,因此训练过程会随着样本数量的加大而变得异常的缓慢。**随机梯度下降法(SGD)**正是为了解决批量梯度下降法这一弊端而提出的。

​ 随机梯度下降法是通过每个样本来迭代更新一次,若样本量很大的情况(例如几十万),那么可能只用其中的几万条或者几千条的样本,就已经将参数迭代到最优解了。对比上面的批量梯度下降,迭代一次需要用十几万训练样本,一次迭代不可能最优,若迭代10次就需要遍历训练样本10次。但SGD伴随的一个问题是噪音较多,使得SGD不是每次迭代都向着整体最优化的方向

  • 优点:训练速度快;
  • 缺点:准确度下降,不是全局最优,不易于并行实现。
4.2.3 小批量梯度下降法MBGD

​ 有上述两种梯度下降法可看出,其各自均有优缺点,但能不能在两种方法之间取得一个折衷呢?即,算法的训练过程较快,且能保证最终参数训练的准确率,这就是小批量梯度下降法的初衷。

参考链接:梯度下降法的三种形式BGD、SGD以及MBGD

5. 例子

# 我们先来对未调参的SVR进行评价: 
from sklearn.svm import SVR     # 引入SVR类
from sklearn.pipeline import make_pipeline   # 引入管道简化学习流程
from sklearn.preprocessing import StandardScaler # 由于SVR基于距离计算,引入对数据进行标准化的类
from sklearn.model_selection import GridSearchCV  # 引入网格搜索调优
from sklearn.model_selection import cross_val_score # 引入K折交叉验证
from sklearn import datasets


boston = datasets.load_boston()     # 返回一个类似于字典的类
X = boston.data
y = boston.target
features = boston.feature_names
pipe_SVR = make_pipeline(StandardScaler(),
                                                         SVR())
score1 = cross_val_score(estimator=pipe_SVR,
                                                     X = X,
                                                     y = y,
                                                     scoring = 'r2',
                                                      cv = 10)       # 10折交叉验证
print("CV accuracy: %.3f +/- %.3f" % ((np.mean(score1)),np.std(score1)))
CV accuracy: 0.187 +/- 0.649

5.1 网格搜索

# 下面我们使用网格搜索来对SVR调参:
from sklearn.pipeline import Pipeline
pipe_svr = Pipeline([("StandardScaler",StandardScaler()),
                                                         ("svr",SVR())])
param_range = [0.0001,0.001,0.01,0.1,1.0,10.0,100.0,1000.0]
param_grid = [{"svr__C":param_range,"svr__kernel":["linear"]},  # 注意__是指两个下划线,一个下划线会报错的
                            {"svr__C":param_range,"svr__gamma":param_range,"svr__kernel":["rbf"]}]
gs = GridSearchCV(estimator=pipe_svr,
                                                     param_grid = param_grid,
                                                     scoring = 'r2',
                                                      cv = 10)       # 10折交叉验证
gs = gs.fit(X,y)
print("网格搜索最优得分:",gs.best_score_)
print("网格搜索最优参数组合:\n",gs.best_params_)
网格搜索最优得分: 0.6081303070817127
网格搜索最优参数组合:
 {'svr__C': 1000.0, 'svr__gamma': 0.001, 'svr__kernel': 'rbf'}

5.2 随机搜索

# 下面我们使用随机搜索来对SVR调参:
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import uniform  # 引入均匀分布设置参数
pipe_svr = Pipeline([("StandardScaler",StandardScaler()),
                                                         ("svr",SVR())])
distributions = dict(svr__C=uniform(loc=1.0, scale=4),    # 构建连续参数的分布
                     svr__kernel=["linear","rbf"],                                   # 离散参数的集合
                    svr__gamma=uniform(loc=0, scale=4))

rs = RandomizedSearchCV(estimator=pipe_svr,
                                                     param_distributions = distributions,
                                                     scoring = 'r2',
                                                      cv = 10)       # 10折交叉验证
rs = rs.fit(X,y)
print("随机搜索最优得分:",rs.best_score_)
print("随机搜索最优参数组合:\n",rs.best_params_)
随机搜索最优得分: 0.3046244976868293
随机搜索最优参数组合:
 {'svr__C': 1.040579963881545, 'svr__gamma': 1.008649319233331, 'svr__kernel': 'linear'}

经过我们不懈的努力,从收集数据集并选择合适的特征、选择度量模型性能的指标、选择具体的模型并进行训练以优化模型到评估模型的性能并调参,我们认识到了如何使用sklearn构建简单回归模型。

6. 小结

在这里插入图片描述

​ 在本章的最后,我们会给出一个具体的案例,整合回归的内容。下面我们来看看机器学习另外一类大问题:分类。与回归一样,分类问题在机器学习的地位非常重要,甚至有的地方用的比回归问题还要多,因此分类问题是十分重要的!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值