天天看点

学习器模型中的超参数(Hyperparameter)怎么选?

作者:腾科IT教育

学习器模型中一般有两类参数:

一类是可以从数据中学习估计得到,我们称为参数(Parameter)。

还有一类参数时无法从数据中估计,只能靠人的经验进行设计指定,我们称为超参数(Hyper parameter)。超参数是在开始学习过程之前设置值的参数。相反,其他参数的值通过训练得出。

我们在选择超参数有两个途径:

1)凭经验;

2)选择不同大小的参数,带入到模型中,挑选表现最好的参数。通过途径2选择超参数时,人力手动调节注意力成本太高,非常不值得。For循环或类似于for循环的方法受限于太过分明的层次,不够简洁与灵活,注意力成本高,易出错。

有一种选择方法叫做网络搜索(GridSearchCV),利用计算机快速计算的特点遍历所有的参数组合,找到最好的参数组合。听起来很高大上,本质上就是暴力搜索。注意的是,该方法在小数据集上很有用,数据集大了就不太适用了。会比较耗费时间和计算资源。数据量比较大的时候可以使用一个快速调优的方法——坐标下降。它其实是一种贪心算法:拿当前对模型影响最大的参数调优,直到最优化;再拿下一个影响最大的参数调优,如此下去,直到所有的参数调整完毕。这个方法的缺点就是可能会调到局部最优而不是全局最优,但是省时间省力。

使用示例:

from sklearn.model_selection import GridSearchCV 
from sklearn.svm import SVR 
from sklearn import datasets 
dataset = datasets.load_iris() 
X = dataset.data 
y = dataset.target 
grid = GridSearchCV( 
    estimator=SVR(kernel='rbf'), 	
    param_grid={ 	
        'C': [0.1, 1, 10, 100], 
        'epsilon': [0.0001, 0.001, 0.01, 0.1, 1, 10], 
        'gamma': [0.001, 0.01, 0.1, 1] 
    }, 
    cv=5, scoring='neg_mean_squared_error', verbose=0, n_jobs=-1) 
grid.fit(X, y) 
print(grid.best_score_) 
print(grid.best_params_)            

还有一种方法叫做随机搜索(RandomizedSearchCV),再参数量较大的时候使用这种方法可以快速或者较好的参数组合,在搜索超参数的时候,如果超参数个数较少(三四个或者更少),那么我们可以采用网格搜索,一种穷尽式的搜索方法。

但是当超参数个数比较多的时候,我们仍然采用网格搜索,那么搜索所需时间将会指数级上升。所以有人就提出了随机搜索的方法,随机在超参数空间中搜索几十几百个点,其中就有可能有比较小的值。这种做法比上面稀疏化网格的做法快,而且实验证明,随机搜索法结果比稀疏网格法稍好。RandomizedSearchCV使用方法和类GridSearchCV 很相似,但他不是尝试所有可能的组合,而是通过选择每一个超参数的一个随机值的特定数量的随机组合,这个方法有两个优点:

相比于整体参数空间,可以选择相对较少的参数组合数量。如果让随机搜索运行,它会探索每个超参数的不同的值 可以方便的通过设定搜索次数,控制超参数搜索的计算量,但是这个方法也有缺点,他会再搜索的过程中逐步偏向某些更加重要的超参数,会影响搜索的方向。

使用示例:

from scipy.stats import randint as sp_randint 
from sklearn.model_selection import RandomizedSearchCV 
from sklearn.datasets import load_digits 
from sklearn.ensemble import RandomForestClassifier 
# 载入数据 
digits = load_digits() 
X, y = digits.data, digits.target 
# 建立一个分类器或者回归器 
clf = RandomForestClassifier(n_estimators=20) 
# 给定参数搜索范围:list or distribution 
param_dist = {"max_depth": [3, None],  # 给定list 
              "max_features": sp_randint(1, 11),  # 给定distribution 
              "min_samples_split": sp_randint(2, 11),  # 给定distribution 
              "bootstrap": [True, False],  # 给定list 
              "criterion": ["gini", "entropy"]}  # 给定list 
# 用RandomSearch+CV选取超参数 
n_iter_search = 20 
random_search=RandomizedSearchCV(clf,param_distributions=param_dist,n_iter=n_iter_search, cv=5, iid=False) 
random_search.fit(X, y) 
print(random_search.best_score_) 
print(random_search.best_params_)            

还有一种方法叫贝叶斯优化(Bayesian optimization),给定一组超参数,为了计算相应的模型泛化误差,我们需要进行一次完整的模型训练,对于大型的深度学习模型可能需要花上几个小时的时间。注意到网格搜索和随机搜索中,不同的超参数采样是相互独立的,一个直接的想法是,能否充分利用已采样数据来决定下一次采样,以提高搜索效率(或者说减少采样次数)。

贝叶斯优化属于一类优化算法,称为基于序列模型的优化(SMBO)算法。这些算法使用先前对损失 f 的观察结果,以确定下一个(最优)点来抽样 f。该算法大致可以概括如下。

1、使用先前评估的点 X 1:n,计算损失 f 的后验期望。

2、在新的点 X 的抽样损失 f,从而最大化f的期望的某些方法。该方法指定 f 域的哪些区域最适于抽样。

3、重复这些步骤,直到满足某些收敛准则

使用例子:

from skopt import BayesSearchCV
import warnings
warnings.filterwarnings("ignore")
from skopt.space import Real, Categorical, Integer
knn = KNeighborsClassifier()
定义参数
grid_param = { 'n_neighbors' : list(range(2,11)) , 
              'algorithm' : ['auto','ball_tree','kd_tree','brute'] }
#初始化贝叶斯搜索
Bayes = BayesSearchCV(knn , grid_param , n_iter=30 , random_state=14)
Bayes.fit(X_train,y_train)
#最好的参数组合
Bayes.best_params_
#最好分数
Bayes.best_score_
#所有的参数组合
Bayes.cv_results_['params']           

继续阅读