5. 对模型超参数进行调优(调参)
岭回归
J
(
w
)
=
∑
i
=
1
N
(
y
i
−
w
0
−
∑
j
=
1
p
w
j
x
i
j
)
2
+
λ
∑
j
=
1
p
w
j
2
(
λ
≥
0
)
w
^
=
(
X
T
X
+
λ
I
)
−
1
X
T
Y
J(w) = \sum_{i=1}^{N}(y_i-w_0-\sum_{j=1}^{p}w_jx_{ij})^2+\lambda \sum_{j=1}^{p}w^2_j (\lambda \ge 0) \\ \hat{w} = (X^TX+\lambda I)^{-1}X^TY
J(w)=i=1∑N(yi−w0−j=1∑pwjxij)2+λj=1∑pwj2(λ≥0)w^=(XTX+λI)−1XTY
5.1 目的
找到最佳参数解
5.2 基础概念
- 参数与超参数:
岭回归的参数 λ \lambda λ和参数 w w w,类似参数 w w w可以通过设定某一个具体的 λ \lambda λ后使用类似于最小二乘法、梯度下降法等方法优化出来的,称为参数;参数 λ \lambda λ无法使用最小二乘法或梯度下降法等优化算法优化出来的数称为超参数。
5.3 模型参数
是模型内部的配置变量,其值可以根据数据进行估计。
- 进行与测试需要参数
- 参数定义了可使用的模型
- 参数是从数据估计中获悉
- 参数通常不手动设置
- 参数通常被保存为学习模型的一部分
- 参数是机器学习算法的关键,通常由过去的训练数据中总结得出
5.4 模型超参数
是模型外部的配置,其值无法从数据中估计
- 超参数通常用于帮助估计模型参数
- 超参数通常由人工指定
- 超参数通常可以使用启发式设置(经验或者启发式算法(不一定有结果))
- 超参数经常被调整为给定的预测建模问题
5.5 调参案例
klearn.model_selection.GridSearchCV(estimator, param_grid, *, scoring=None, n_jobs=None, iid='deprecated', refit=True, cv=None, verbose=0, pre_dispatch='2*n_jobs', error_score=nan, return_train_score=False)
使用SVR的例子,结合管道来进行调优:
SVR的解形:
f
(
x
)
=
∑
i
=
1
N
(
α
^
−
α
i
)
x
i
T
x
+
b
f(x) = \sum_{i=1}^{N}(\hat{\alpha}-\alpha_i)x_i^Tx+b
f(x)=i=1∑N(α^−αi)xiTx+b
(1) 对未调参的SVR进行评价
from sklearn.svm import SVR #引入SVR类
from sklearn.pipeline import make_pipeline #引入管道简化学习流程
from sklearn.preprocessing import StandardScaler # SVR基于距离计算,对数据进行标准化
from sklearn.model_selection import cross_val_score #引入K折交叉验证
from sklearn import datasets
import numpy as np
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)
# k折交叉验证之后取平均值作为结果
print("CV accuracy: %.3f +/- %.3f" % (np.mean(score1),np.std(score1)))
CV accuracy: 0.187 +/- 0.649
(2) 使用网格搜索对SVR调参
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV #引入网格搜索调优
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'}
param_grid的值设置匹配到SVR模型的设置
- svr__C:误差的惩罚参数
- svr__kernel:核函数。‘linear’、‘poly’[多项式]、‘rbf’[径向基核]、‘sigmod’
- svr__gamma:gamma是选择RBF函数作为kernel后,该函数自带的一个参数,gamma越大,支持向量越少,gamma值越小,支持向量越多
(3) 使用随机搜索来对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)
rs = rs.fit(X,y)
print("随机搜索最优得分:",rs.best_score_)
print("随机搜索最优参数组合:",rs.best_params_)
随机搜索最优得分: 0.30356099462119335
随机搜索最优参数组合: {'svr__C': 1.0581182932144224, 'svr__gamma': 0.043960471603663454, 'svr__kernel': 'linear'}
问题点:为什么最优解kernel为linear,但是gamma却有值
- uniform(loc, scale):获得[loc, loc+scale]的均匀分布。默认[0,1]分布
Z. 补充知识
Z1. Pipeline
from sklearn.pipeline import make_pipeline
from sklearn.pipeline import Pipeline
https://cloud.tencent.com/developer/article/1693921
原理
- 处理机制就像是把所有模型塞到一个管子里,然后依次对数据进行处理,得到最终的分类结果。
- 例如模型一可以是一个数据标准化处理,模型二可以是特征选择模型或特征提取模型,模型三可以是一个分类器或预测模型
- pipeline除最后一个之外的所有评估其必须是交换器,最后一个评估器可以是任何类型(transformer, classifier, regressor),若最后一个评估器是分类器,则整个pipeline作为分类器。
- 调用pipeline的fit方法,使用前n-1个交换器处理特征,之后传递给最后的estimator进行训练。pipeline继承最后一个估计器的所有方法
完整的pipeline步骤
- 首先对数据进行预处理,比如缺失值的处理
- 数据的标准化
- 降维
- 特征选择算法
- 分类或预测或聚类算法(估计器estimator)
用法
sklearn.pipeline.make_pipeline(steps,memory=None,verbose=False)
steps:步骤,不需要命名【Pipeline需要使用(key,value):key-步骤名称;value-评估对象】
memory:内存参数
Z2. cross_val_score
from sklearn.model_selection import cross_val_score
k折交叉验证:
交叉验证既可以解决数据集的数据量不够大问题,也可以解决参数调优的问题。
- 首先,将全部样本划分为k个大小相等的样本子集
- 依次遍历这k个子集,每次将房前子集作为验证集,其余所有样本作为训练集,进行模型的训练
- 最后将k次评估指标的平均值作为最终的评估指标
- 在实际实验中,k通常取10
sklearn.model_selection.cross_val_score(estimator, X, y=None, groups=None, scoring=None, cv=’warn’, n_jobs=None, verbose=0, fit_params=None, pre_dispatch=‘2*n_jobs’, error_score=’raise-deprecating’)
参数:
- estimator:需要使用交叉验证的算法
- X:
- y:
- groups:将数据集分割为训练/测试集时使用的样本组标签(一般不用)
- scoring:验证方式【重要】,
- cv:交叉验证折数或可迭代的次数
- n_jobs:同时工作的CPU个数(-1为全部)
- verbose:详细程度
- fit_params:传递给估计器的拟合方法的参数
Z3. GridSearchCV
from sklearn.pipeline import Pipeline
sklearn.model_selection.GridSearchCV(estimator, param_grid, *, scoring=None, n_jobs=None, iid='deprecated', refit=True, cv=None, verbose=0, pre_dispatch='2*n_jobs', error_score=nan, return_train_score=False)
原理: 在指定的参数范围内,按步长依次调整参数,利用调整的参数训练学习器,从所有的参数中找到在验证集上精度最高的参数。(适用于小数量级数据)
参数:
- estimator:选择使用的分类器,并且传入除需要确定最佳的参数之外的其他参数。每一个分类器都需要一个scoring参数
- param_grid:需要最优化的参数的取值,值是字典或列表
- scoring = None:模型评价标准,默认None,需要使用score函数,根据所选的模型评价标准不同。
- fit_params:None
- n_jobs:并行数
- iid:True。默认为各个样本fold概率分布一致,误差估计为所有样本之和,而非各个fold的平均。
- refit:True。程序将会以交叉验证训练集得到的最佳参数,重新对所有可用的训练集与开发集进行,作为最终用于性能评估的最佳模型参数
- cv:None。交叉验证参数,默认None,使用三折交叉验证。指定fold数量,默认为3,也可以是yield训练/测试数据的生成器。
scoring
属性:
- cv_results_:具有键作为列标题和值作为列的dict,可以导入到DataFrame中。注意,“params”键用于存储所有参数候选项的参数设置列表。
- best_estimator_:通过搜索选择的估计器,即在左侧数据上给出最高分数(或指定的最小损失)的估计器。 如果refit = False,则不可用。
- best_score_:best_estimator的分数
- best_params_:在保存数据上给出最佳结果的参数设置
- best_index_:对应于最佳候选参数设置的索引
- scorer_:
- n_splits_:
- grid_scores:
Z4. RandomizedSearchCV
原理: 随机搜索不是尝试所有可能的组合,而是通过选择每一个超参数的随机值的特定数量的随机组合
搜索策略:
- 对搜索范围是distribution的超参数,根据给定的distribution随机采样;对搜索范围是list的超参数,在给定的list中等概率采样
- 对得到的n_inter组采样结果进行遍历
(如果给定的搜索范围均为list,采用不放回抽样)
sklearn.model_selection.RandomizedSearchCV(estimator,param_distributions,*,n_iter = 10,评分= None,n_jobs = None,iid ='deprecated',refit = True,cv = None,verbose = 0,pre_dispatch ='2 * n_jobs',random_state = None,error_score = nan,return_train_score = False)
参数:
- estimator
- param_distributions:分布必须提供一种rvs 抽样方法(例如scipy.stats.distributions中的抽样方法)。如果给出列表,则对其进行统一采样。如果给出了字典列表,则首先对一个字典进行统一采样,然后如上所述使用该字典对参数进行采样
- n_iter:采样的参数设置数量
- scoring
- n_jobs
- cv:交叉验证切分策略。None默认5折
- refit
- random_state:伪随机数生成器状态
属性:
- cv_results_
- best_estimator_
- best_score_
- best_params_
- best_index_
- scorer_
- n_splits_
- refit_time_
方法:
- decision_function(X):最优参数在估计器上调用
- fit(X):将所有参数组合进行拟合
- get_params()
- predict()
- predict_log_proba
- predict_proba
- score()
- set_parmas
- transform