1.1 调参目的
调参的根本目的实际上就是要找到一组合适的超参数(超参数是指在开始学习过程之前设置值的参数,而不是通过训练得到的参数数据),使得模型具有更好的效果。
更好的效果也可以理解为是让模型得到更好的泛化性能(泛化性能可以定义为样本外的预测效果,即在训练集和测试集或者更大的数据集中都能很好的决策)。泛化性能较差的情况主要表现为过拟合和欠拟合。
欠拟合: 是指模型没有能够很好的学习到数据特征,不能很好的拟合数据,表现为预测值与真实值之间存在较大的偏差。如上图第一个示例。
导致欠拟合的原因:预测函数的学习能力不足,预测模型过于简单(具体到预测算法模型如:特征项不够)
过拟合: 模型学习数据的能力太强(复杂的预测函数),除了学习到数据整体的特性以外,还额外学习到了训练集的一些特性,主要表现为能够很好的拟合训练集,但是不能很好的预测测试样本(即,泛化能力太差)
导致过拟合的原因: 预测模型过于复杂(包含过多的特征项),并且往往训练集样本过少,且训练数据中还包含一些不合理的数据样本,最终导致预测模型能够很好的拟合训练集但是不能很好的拟合测试样本。
1.2 调参后的评估方法
目前使用最为广泛的评估方法之一便是交叉验证,下图是模型训练中典型交叉验证工作流的流程图。
右侧是数据的分割,分为训练集和测试集,训练集会调用Parameters参数范围进行交叉验证,直至获取最佳的参数。使用最佳参数对所有Training data进行训练,再对最先分出的Test data进行验证,取得最后的分数
交叉验证既可以解决数据集的数据量不够大问题,也可以解决参数调优的问题。常见的交叉验证一般使用k折交叉验证。
sklearn官方文档中给出了这样一张图很清楚地描述了k折交叉验证过程。它的思路非常简单:首先将数据集分为测试集和训练集,然后将训练数据随机均分k份。使用其中1份做测试集,剩余k-1份做训练集。通过 k 次训练后,我们得到了 k 个不同的模型。评估 k 个模型的效果,从中挑选效果最好的超参数。
在sklearn中,用cross_val_score来实现交叉验证
>>> from sklearn import datasets, linear_model
>>> from sklearn.model_selection import cross_val_score
>>> diabetes = datasets.load_diabetes()
>>> X = diabetes.data[:150]
>>> y = diabetes.target[:150]
>>> lasso = linear_model.Lasso()
>>> print(cross_val_score(lasso, X, y, cv=3))
[0.3315057 0.08022103 0.03531816]
在机器学习的自动调参方法中,GridSearchCV即网格搜索的交叉验证法,这是最为常用的方法之一。GridSearchCV适合小数据集。相当于写一堆循环,自己设定参数列表,一个一个试,找到最合适的参数。
2.1.1 GridSearchCV demo
>>> from sklearn import svm, datasets
>>> from sklearn.model_selection import GridSearchCV
>>> iris = datasets.load_iris()
>>> parameters = {'kernel':('linear', 'rbf'), 'C':[1, 10]}
>>> svc = svm.SVC()
>>> clf = GridSearchCV(svc, parameters)
>>> clf.fit(iris.data, iris.target)
GridSearchCV(estimator=SVC(),
param_grid={'C': [1, 10], 'kernel': ('linear', 'rbf')})
>>> sorted(clf.cv_results_.keys())
['mean_fit_time', 'mean_score_time', 'mean_test_score',...
'param_C', 'param_kernel', 'params',...
'rank_test_score', 'split0_test_score',...
'split2_test_score', ...
'std_fit_time', 'std_score_time', 'std_test_score']
2.1.2 参数说明
estimator:所使用的分类器,比如:estimator=RandomForestClassifier(min_samples_split=100, min_samples_leaf=20, max_depth=8, max_features=’sqrt’, random_state=10),并且传入除需要确定最佳的参数之外的其他参数。每个分类器都需要一个scoring参数或者score方法。被调参的模型,即上一教程中提到的各类模型的class,比如tree,RandomForestRegressor等具体模型,以对象实例的形式传递。
param_grid:值为字典或列表,即需要最优化的参数的取值,param_grid =param_test1,param_test1 = {‘n_estimators’:range(10,71,10)}。被调参数的grid,以字典形式传递。
scoring:准确评价标准,默认为None(使用estimator的误差估计函数),这时需要使用score函数;或者如scoring=’roc_auc’,根据所选模型不同,评价准则不同。模型评价指标,给出具体指标的名称字符串即可,如’accuracy’,’neg_mean_squared_error’等。
cv:交叉验证参数,默认为None。这个变量比较复杂。一般来说我们直接取整数即可,也就是k-fold中的k即可。特别地当k等于样本个数时,它就是留一法。
refit:默认为True,程序将会以交叉验证训练集得到的最佳参数,重新对所有可用的训练集与测试集进行,作为最终用于性能评估的最佳模型参数。即在搜索参数结束后,用最佳参数结果再次fit一遍全部数据集。
iid:默认True,为True时,默认为各个样本fold概率分布一致,误差估计为所有样本之和,而非各个fold的平均。
verbose:日志冗长度,int:冗长度,0:不输出训练过程,1:偶尔输出,>1:对每个子模型都输出。
n_jobs:并行数,int:个数,-1:跟CPU核数一致, 1:默认值。并行计算是sklearn中的另一个亮点,它对一些能够并行的方法提前进行了封装,在使用的时候只需要简单一个参数即可。在GridSearchCV中,只需要在输入参数中设定n_jobs大于等于2即可,这个参数即是代表需要用来并行的核心数量。。
pre_dispatch:指定总共分发的并行任务数。当n_jobs大于1时,数据将在每个运行点进行复制,这可能导致OOM,而设置pre_dispatch参数,则可以预先划分总共的job数量,使数据最多被复制pre_dispatch次,进行预测的常用方法和属性
grid_scores_:给出不同参数情况下的评价结果
best_params_:描述了已取得最佳结果的参数的组合
best_score_:成员提供优化过程期间观察到的最好的评分
2.1.3 类属性
cv_results_:各参数组合交叉验证的结果,
best_estimator_:搜索选择的估计器,即在数据集上给出最高分数的估计器。
best_score_:最佳估计器的平均交叉验证结果
2.2 RandomizedSearchCV
GridSearchCV的原理很简明,就是程序去挨个尝试每一组超参数,然后选取最好的那一组。可以想象,这个是比较费时间的,面临着维度灾难。因此James Bergstra和Yoshua Bengio在2012年提出了超参数优化的RandomSearch方法。
2.2.1 RandomizedSearchCV demo
>>> from sklearn.datasets import load_iris
>>> from sklearn.linear_model import LogisticRegression
>>> from sklearn.model_selection import RandomizedSearchCV
>>> from scipy.stats import uniform
>>> iris = load_iris()
>>> logistic = LogisticRegression(solver='saga', tol=1e-2, max_iter=200,
... random_state=0)
>>> distributions = dict(C=uniform(loc=0, scale=4),
... penalty=['l2', 'l1'])
>>> clf = RandomizedSearchCV(logistic, distributions, random_state=0)
>>> search = clf.fit(iris.data, iris.target)
>>> search.best_params_
{'C': 2..., 'penalty': 'l1'}
2.2.2 RandomSearchCV是如何”随机搜索”的
考察其源代码,其搜索策略如下:
(a)对于搜索范围是distribution的超参数,根据给定的distribution随机采样;
(b)对于搜索范围是list的超参数,在给定的list中等概率采样;
(c)对a、b两步中得到的n_iter组采样结果,进行遍历。
(补充)如果给定的搜索范围均为list,则不放回抽样n_iter次。
2.2.3 RandomSearch为什么会有效
下图是原论文里说明为何随机搜索在某些情况下会更有效的原理示意图:
(a)目标函数为 f(x,y)=g(x)+h(y),其中绿色为g(x),黄色为h(y),目的是求f的最大值。
(b)其中由于g(x)数值上要明显大于h(y),因此有f(x,y)=g(x)+h(y)≈g(x),也就是说在整体求解f(x,y)最大值的过程中,g(x)的影响明显大于h(y)。
(c)两个图都进行9次实验(搜索),可以看到左图实际探索了各三个点(在横轴和纵轴上的投影均为3个),而右图探索了9个不同的点(横轴纵轴均是,不过实际上横轴影响更大)。
(d)右图更可能找到目标函数的最大值。
因此引入随机因素在某些情况下可以提高寻优效率。
https://blog.csdn.net/qq_40206371/article/details/127591596
https://blog.csdn.net/qq_36535820/article/details/119762665
https://blog.csdn.net/qq_36810398/article/details/86699842
原文始发于微信公众号(山石网科安全技术研究院):机器学习的自动调参