赞
踩
在机器学习模型中,需要人工选择的参数称为超参数。比如随机森林中决策树的个数,人工神经网络模型中隐藏层层数和每层的节点个数,正则项中常数大小等等,他们都需要事先指定。超参数选择不恰当,就会出现欠拟合或者过拟合的问题。而在选择超参数的时候,有两个途径,一个是凭经验微调,另一个就是选择不同大小的参数,带入模型中,挑选表现最好的参数。
微调的一种方法是手工调制超参数,直到找到一个好的超参数组合,这么做的话会非常冗长,你也可能没有时间探索多种组合,所以可以使用Scikit-Learn的GridSearchCV来做这项搜索工作。下面让我们一一探索。
GridSearchCV的名字其实可以拆分为两部分,GridSearch和CV,即网格搜索和交叉验证。这两个名字都非常好理解。网格搜索,搜索的是参数,即在指定的参数范围内,按步长依次调整参数,利用调整的参数训练学习器,从所有的参数中找到在验证集上精度最高的参数,这其实是一个训练和比较的过程。
GridSearchCV可以保证在指定的参数范围内找到精度最高的参数,但是这也是网格搜索的缺陷所在,他要求遍历所有可能参数的组合,在面对大数据集和多参数的情况下,非常耗时。
Grid Search:一种调参手段;穷举搜索:在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果。其原理就像是在数组里找到最大值。这种方法的主要缺点是比较耗时!
所以网格搜索适用于三四个(或者更少)的超参数(当超参数的数量增长时,网格搜索的计算复杂度会呈现指数增长,这时候则使用随机搜索),用户列出一个较小的超参数值域,这些超参数至于的笛卡尔积(排列组合)为一组组超参数。网格搜索算法使用每组超参数训练模型并挑选验证集误差最小的超参数组合。
2.1,以随机森林为例说明GridSearch网格搜索
下面代码,我们要搜索两种网格,一种是n_estimators,一种是max_features。GridSearch会挑选出最适合的超参数值。
1 2 3 4 5 6 7 8 9 10 11 |
|
sklearn 根据param_grid的值,首先会评估3×4=12种n_estimators和max_features的组合方式,接下来在会在bootstrap=False的情况下(默认该值为True),评估2×3=6种12种n_estimators和max_features的组合方式,所以最终会有12+6=18种不同的超参数组合方式,而每一种组合方式要在训练集上训练5次, 所以一共要训练18×5=90 次,当训练结束后,你可以通过best_params_获得最好的组合方式。
1 |
|
输出结果如下:
1 |
|
得到最好的模型:
1 |
|
输出如下:
1 2 3 4 5 6 |
|
如果GridSearchCV初始化时,refit=True(默认的初始化值),在交叉验证时,一旦发现最好的模型(estimator),将会在整个训练集上重新训练,这通常是一个好主意,因为使用更多的数据集会提升模型的性能。
以上面有两个参数的模型为例,参数a有3中可能,参数b有4种可能,把所有可能性列出来,可以表示成一个3*4的表格,其中每个cell就是一个网格,循环过程就像是在每个网格里遍历,搜索,所以叫grid search。
文献地址可以参考:请点击我
所谓的模型配置,一般统称为模型的超参数(Hyperparameters),比如KNN算法中的K值,SVM中不同的核函数(Kernal)等。多数情况下,超参数等选择是无限的。在有限的时间内,除了可以验证人工预设几种超参数组合以外,也可以通过启发式的搜索方法对超参数组合进行调优。称这种启发式的超参数搜索方法为网格搜索。
我们在搜索超参数的时候,如果超参数个数较少(三四个或者更少),那么我们可以采用网格搜索,一种穷尽式的搜索方法。但是当超参数个数比较多的时候,我们仍然采用网格搜索,那么搜索所需时间将会指数级上升。
所以有人就提出了随机搜索的方法,随机在超参数空间中搜索几十几百个点,其中就有可能有比较小的值。这种做法比上面稀疏化网格的做法快,而且实验证明,随机搜索法结果比稀疏网格法稍好。
RandomizedSearchCV使用方法和类GridSearchCV 很相似,但他不是尝试所有可能的组合,而是通过选择每一个超参数的一个随机值的特定数量的随机组合,这个方法有两个优点:
RandomizedSearchCV的使用方法其实是和GridSearchCV一致的,但它以随机在参数空间中采样的方式代替了GridSearchCV对于参数的网格搜索,在对于有连续变量的参数时,RandomizedSearchCV会将其当做一个分布进行采样进行这是网格搜索做不到的,它的搜索能力取决于设定的n_iter参数,同样的给出代码。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
建议使用随机搜索。
超参数搜索——网格搜索&并行搜索代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
使用的数据集是小数据集 手写数字数据集 load_digits() 分类 数据规模 5620*64
(sklearn中的小数据可以直接使用,大数据集在第一次使用的时候会自动下载)
比较随机森林超参数优化的随机搜索和网格搜索。所有影响学习的参数都是同时搜索的(除了估计值的数量,它会造成时间/质量的权衡)。
随机搜索和网格搜索探索的是完全相同的参数空间。参数设置的结果非常相似,而随机搜索的运行时间要低的多。
随机搜索的性能稍差,不过这很可能是噪声效应,不会延续到外置测试集
注意:在实践中,人们不会使用网格搜索同时搜索这么多不同的参数,而是只选择那些被认为最重要的参数。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
|
结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
sklearn的Grid Search官网地址:请点击我
GridSearchCV,它存在的意义就是自动调参,只要把参数输进去,就能给出最优化结果和参数。但是这个方法适合于小数据集,一旦数据的量级上去了,很难得到结果。这个时候就需要动脑筋了。数据量比较大的时候可以使用一个快速调优的方法——坐标下降。它其实是一种贪心算法:拿当前对模型影响最大的参数调参,直到最优化;再拿下一个影响最大的参数调优,如此下去,直到所有的参数调整完毕。这个方法的缺点就是可能会跳到局部最优而不是全局最优,但是省时间省力,巨大的优势面前,还是试一试,后续可以再拿bagging再优化。
通常算法不够好,需要调试参数时必不可少。比如SVM的惩罚因子C,核函数kernel,gamma参数等,对于不同的数据使用不同的参数,结果效果可能差1~5个点,sklearn为我们专门调试参数的函数grid_search。
参数如下:
1 2 3 |
|
说明如下:
1)estimator:选择使用的分类器,并且传入除需要确定最佳的参数之外的其他参数。每一个分类器都需要一个scoring参数,或者score方法:如estimator = RandomForestClassifier(min_sample_split=100,min_samples_leaf = 20,max_depth = 8,max_features = 'sqrt' , random_state =10),
2)param_grid:需要最优化的参数的取值,值为字典或者列表,例如:param_grid = param_test1,param_test1 = {'n_estimators' : range(10,71,10)}
3)scoring = None :模型评价标准,默认为None,这时需要使用score函数;或者如scoring = 'roc_auc',根据所选模型不同,评价准则不同,字符串(函数名),或是可调用对象,需要其函数签名,形如:scorer(estimator,X,y);如果是None,则使用estimator的误差估计函数。
4)fit_para,s = None
5)n_jobs = 1 : n_jobs:并行数,int:个数,-1:跟CPU核数一致,1:默认值
6)iid = True:iid:默认为True,为True时,默认为各个样本fold概率分布一致,误差估计为所有样本之和,而非各个fold的平均。
7)refit = True :默认为True,程序将会以交叉验证训练集得到的最佳参数,重新对所有可能的训练集与开发集进行,作为最终用于性能评估的最佳模型参数。即在搜索参数结束后,用最佳参数结果再次fit一遍全部数据集。
8)cv = None:交叉验证参数,默认None,使用三折交叉验证。指定fold数量,默认为3,也可以是yield训练/测试数据的生成器。
9)verbose = 0 ,scoring = None verbose:日志冗长度,int:冗长度,0:不输出训练过程,1:偶尔输出,>1:对每个子模型都输出。
10)pre_dispatch = '2*n_jobs' :指定总共发的并行任务数,当n_jobs大于1时候,数据将在每个运行点进行复制,这可能导致OOM,而设置pre_dispatch参数,则可以预先划分总共的job数量,使数据最多被复制pre_dispatch次。
(1) cv_results_ : dict of numpy (masked) ndarrays
具有键作为列标题和值作为列的dict,可以导入到DataFrame中。注意,“params”键用于存储所有参数候选项的参数设置列表。
(2) best_estimator_ : estimator
通过搜索选择的估计器,即在左侧数据上给出最高分数(或指定的最小损失)的估计器。如果refit = False,则不可用。
(3)best_score_ :float best_estimator的分数
(4)best_parmas_ : dict 在保存数据上给出最佳结果的参数设置
(5) best_index_ : int 对应于最佳候选参数设置的索引(cv_results_数组)
search.cv_results _ ['params'] [search.best_index_]中的dict给出了最佳模型的参数设置,给出了最高的平均分数(search.best_score_)。
(6)scorer_ : function
Scorer function used on the held out data to choose the best parameters for the model.
(7)n_splits_ : int
The number of cross-validation splits (folds/iterations).
3.1 网格搜索算法与K折交叉验证理论知识
网格搜索算法是一种通过遍历给定的参数组合来优化模型表现的方法。
以决策树为例,当我们确定了要使用决策树算法的时候,为了能够更好地拟合和预测,我们需要调整它的参数。在决策树算法中,我们通常选择的参数是决策树的最大深度。
于是下面我们会给出一系列的最大深度的值,比如{‘max_depth’:[1,2,3,4,5] },我们就会尽可能包含最优最大深度。
不过我们如何知道哪个最大深度的模型是最好的呢?我们需要一种可靠的评分方法,对每个最大深度的决策树模型都进行评价,这其中非常经典的一种方法就是交叉验证,下面我们就以K折交叉验证为例,详细介绍一下其算法过程。
首先我们先看一下数据集时如何分割的,我们拿到的原始数据集首先会按照一定的比例划分出训练集和测试集。比如下图,以8:2分割的数据集:
训练集是用来训练我们的模型,它的作用就像我们平时做的练习题;测试集用来评估我们训练好的模型表现如何,它不能被提前被模型看到。
因此,在K折交叉验证中,我们用到的数据是训练集中的所有数据,我们将训练集的所有数据平均划分出K份(通常选择K=10),取第K份作为验证集,它的作用就像我们用来估计高考分数的模拟题,余下的K-1份作为交叉验证的训练集。
对于我们最开始选择的决策树的5个最大深度,以max_depth=1为例,我们先用第2-10份数据作为训练集训练模型,用第一份数据作为验证集对这次训练的模型进行评分,得到第一个分数;然后重新构建一个max_depth = 1的决策树,用第1和3-10份数据作为训练集训练模型,用第2份数据作为验证集对这次训练的模型进行评分,得到第二个分数.....以此类推,最后构建一个max_depth = 1的决策树用第1-9份数据作为训练集训练模型,用第10份数据作为验证集对这次训练的模型进行评分,得到10个验证分数,然后计算着10个验证分数的平均分数,就是max_depth = 1的决策树模型的最终验证分数。
对于max_depth = 2,3,4,5时,分别进行和max_depth =1 相同的交叉验证过程,得到他们的最终验证分数,然后我们就可以对这5个最大深度的决策树的最终验证分数进行比较,分数最高的那个就是最优最大深度,我们利用最优参数在全部训练集上训练一个新的模型,整个模型就是最优模型。
3.2 简单的利用决策树预测乳腺癌的例子
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
|
结果:
1 2 3 4 5 6 7 |
|
问题描述:
Python运行代码的时候,到gsearch1.grid_scores_ 时报错:
1 |
|
原因:
之所以出现以上问题,原因在于grid_scores_在sklearn0.20版本中已被删除,取而代之的是cv_results_。
解决方法:
将下面代码:
1 |
|
换成:
1 |
|
问题描述:
Python运行代码时候,到from sklearn.grid_search import GridSearchCV时报错:
1 |
|
原因:
sklearn.grid_search模块在0.18版本中被弃用,它所支持的类转移到model_selection 模板中。还要注意,新的CV迭代器的接口与这个模块的接口不同,sklearn.grid_search在0.20中被删除。
解决方法:
将下面代码
1 |
|
修改成:
1 |
|
参考文献:https://blog.51cto.com/emily18/2088128
https://blog.csdn.net/jh1137921986/article/details/79827945
https://blog.csdn.net/juezhanangle/article/details/80051256
不经一番彻骨寒 怎得梅花扑鼻香
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。