超参数是估计器中不能直接学习的参数。在scikit-learn中,它们作为参数传递给估计器类的构造函数。典型的例子包括
C
,
kernel
和用于支持向量分类器的
gamma
,用于Lasso的
alpha
等。
调参即为搜索超参数空间以获得最佳的
交叉验证(cross validation)
分数。
构造估计器时提供的任何参数都可以以这种方式来优化。具体来说,要查找给定估计器的所有参数的名称和当前值,请使用:
estimator.get_params()
搜索包括:
- 估计器(回归器或分类器,如
sklearn.svm.SVC()
); - 参数空间;
- 搜索或抽样候选值的方法;
- 交叉验证方案;
- 得分函数。
GridSearchCV
详尽地考虑所有参数组合,而
RandomizedSearchCV
可以从具有指定分布的参数空间中采样给定数量的候选值。在描述了这些工具之后,我们详细介绍了适用于这两种方法的
最佳实践
。
请注意,有一小部分参数通常会对模型的预测或计算性能产生很大影响,而其他参数则可以保留其默认值。建议阅读estimator类的文档,以便更好地理解它们的预期行为,也可以阅读随附的参考文献。
1. 穷尽网格搜索(Exhaustive Grid Search)
GridSearchCV
提供的网格搜索从
param_grid
参数指定的参数值网格中进行穷举,生成候选值。例如,以下
param_grid
:
param_grid = [
{'C': [1, 10, 100, 1000], 'kernel': ['linear']},
{'C': [1, 10, 100, 1000], 'gamma': [0.001, 0.0001], 'kernel': ['rbf']},
]
指定两个网格搜索:一个是具有线性内核的网格,并且C值在[1、10、100、1000]中,另一个是具有RBF内核的网格,C值的交叉积(cross-product )在[1、10、100、1000]中,gamma值在[0.001、0.0001]中。
GridSearchCV
实例实现估计器API:当将其“拟合”到一个数据集上时,所有可能的参数值组合都将被计算并保留最佳组合。
示例:
- 关于数字数据集上的网格搜索计算示例,请参见使用交叉验证网格搜索的参数估计。
- 有关使用
pipeline.Pipeline
实例的带分类器(这里是一个使用弹性网(elastic net)和L2惩罚项的SGD训练的线性支持向量机)的文本文档特征提取器(n-gram计数矢量器(count vectorizer)和TF-IDF转换器)的网格搜索耦合参数示例,请参见文本特征提取和评估的示例管道。 - 有关在iris数据集上交叉验证循环内网格搜索的示例,请参嵌套交叉验证与非嵌套交叉验证。这是使用网格搜索评估模型性能的最佳实践。
- 请参阅在cross_val_score和GridSearchCV上的多指标评估演示,以获取同时评估多个指标的
GridSearchCV
示例。 - 有关在
GridSearchCV
中使用refit=callable
接口的示例,请参见平衡模型复杂性和交叉验证分数。这个例子展示了在识别“最佳”估计器时这个接口如何增加一定的灵活性。此接口也可用于多指标评估。
2. 随机参数优化(Randomized Parameter Optimization)
虽然使用参数设置网格是当前使用最广泛的参数优化方法,但其他搜索方法具有更有利的特性。RandomizedSearchCV
实现对参数的随机搜索,其中每个设置都从可能的参数值上的分布中进行采样。与穷尽搜索相比,这有两个主要好处:
- 预算的选择可以不受参数数量和可能值的影响。
- 添加不影响性能的参数不会降低效率。
GridSearchCV
指定参数非常相似。此外,计算预算,即抽样候选值(sampled candidates)的数量或抽样迭代(sampling iterations)次数,是使用
n_iter
参数指定的。对于每个参数,可以指定可能值的分布或离散选择列表(将统一采样):
{'C': scipy.stats.expon(scale=100), 'gamma': scipy.stats.expon(scale=.1),
'kernel': ['rbf'], 'class_weight':['balanced', None]}
此示例使用
scipy.stats
模块,该模块包含许多采样参数的有用分布,如
expon
,
gamma
,
uniform
或
randint
。
原则上,可以传递任何提供
rvs
(random variate sample)方法来采样值。对
rvs
函数的调用应在连续调用时从可能的参数值中提供独立的随机样本。
警告 scipy 0.16之前版本的对于连续参数,例如上面的scipy.stats
中不允许指定随机状态。相反,它们使用全局numpy随机状态,可以通过np.random.seed
播种,也可以使用np.random.set_state
设置。但是,从scikit-learn 0.18开始,sklearn.model_selection
模块设置用户提供的随机状态(如果scipy>=0.16也可用)。
C
,指定连续分布以充分利用随机化是很重要的。这样,增大
n_iter
值将使得搜索更精细。
通过
loguniform
可以得到一个连续的log-uniform随机变量。这是log-spaced参数的连续版本。例如,要在上面指定
C
,可以使用
loguniform(1, 100)
,而不是
[1, 10, 100]
或
np.logspace(0, 2, num=1000)
。这是SciPy's
stats.reciprocal
的别名。
在上述网格搜索的示例中,我们可以指定一个连续的随机变量,该变量在
1e0
和
1e3
之间呈log-uniformly分布:
from sklearn.utils.fixes import loguniform
{'C': loguniform(1e0, 1e3),
'gamma': loguniform(1e-4, 1e-3),
'kernel': ['rbf'],
'class_weight':['balanced', None]}
示例:
- 比较用于超参数估计的随机搜索和网格搜索 比较随机搜索和网格搜索的使用和效率。
- Bergstra, J. and Bengio, Y., Random search for hyper-parameter optimization, The Journal of Machine Learning Research (2012)
3. 参数搜索技巧
3.1. 指定目标度量(objective metric)
默认情况下,参数搜索使用估计器的score
函数来评估参数设置的性能。这些是用于分类的
sklearn.metrics.accuracy_score
和用于回归的
sklearn.metrics.r2_score
。对于某些应用程序,其他评分函数更适合(例如在不平衡分类中,准确度评分(accuracy score)通常不具信息性(uninformative))。另一个评分函数可以通过
scoring
参数指定给
GridSearchCV
、
RandomizedSearchCV
和下面描述的许多专用交叉验证工具。详见
评分参数:定义模型评价规则
。
3.2. 指定多个评估指标
GridSearchCV
和
RandomizedSearchCV
允许为
scoring
参数指定多个度量指标。
多指标评分(Multimetric scoring)可以指定为预定义分数名称的字符串列表,也可以指定将分数名称映射到分数函数和/或预定义分数名称的字典(dict)。有关详细信息,请参见
使用多指标评估
。
当指定多个度量指标时,
refit
参数必须设置为在其中可以找到
best_params_
,并用于在整个数据集上构建
best_estimator_
的度量(字符串)。如果搜索不应该refit,请设置
refit=False
。将refit保留为默认值
None
将在使用多个度量时导致错误。
有关示例用法,请参见
在cross_val_score和GridSearchCV上的多指标评估演示
。
3.3. 复合估计器(Composite estimators)与参数空间
GridSearchCV
和
RandomizedSearchCV
允许使用专用语法
__
搜索复合或嵌套估计器的参数,如
Pipeline
,
ColumnTransformer
,
VotingClassifier
或者
CalibratedClassifierCV
:
>>> from sklearn.model_selection import GridSearchCV
>>> from sklearn.calibration import CalibratedClassifierCV
>>> from sklearn.ensemble import RandomForestClassifier
>>> from sklearn.datasets import make_moons
>>> X, y = make_moons()
>>> calibrated_forest = CalibratedClassifierCV(
... base_estimator=RandomForestClassifier(n_estimators=10))
>>> param_grid = {
... 'base_estimator__max_depth': [2, 4, 6, 8]}
>>> search = GridSearchCV(calibrated_forest, param_grid, cv=5)
>>> search.fit(X, y)
GridSearchCV(cv=5,
estimator=CalibratedClassifierCV(...),
param_grid={'base_estimator__max_depth': [2, 4, 6, 8]})
在本例中嵌套估计器的参数名是
base_estimator
。如果
meta-estimator
被构造为
pipeline.Pipeline
中估计器的集合,则引用估计器的名称,请参见
嵌套参数
。实际上,可以有几个层次的嵌套:
>>> from sklearn.pipeline import Pipeline
>>> from sklearn.feature_selection import SelectKBest
>>> pipe = Pipeline([
... ('select', SelectKBest()),
... ('model', calibrated_forest)])
>>> param_grid = {
... 'select__k': [1, 2],
... 'model__base_estimator__max_depth': [2, 4, 6, 8]}
>>> search = GridSearchCV(pipe, param_grid, cv=5).fit(X, y)
3.4. 模型选择:开发与评估
通过评估各种参数设置进行模型选择可以看作是使用标记数据“训练”网格参数的一种方法。 在模型评估结果时,重要的是对网格搜索过程中未见过的保留样本执行此操作:建议将数据拆分为开发集(development set)(将被送到GridSearchCV
的实例)和计算性能指标的评估集(evaluation set)。
这可用
train_test_split
工具函数来实现。
3.5. 并行机制
GridSearchCV
和
RandomizedSearchCV
独立评估每个参数设置。如果您的操作系统支持并行,则可以使用关键字
n_jobs=-1
并行运行计算。有关详细信息,请参见函数签名(function signature)。
3.6. 对异常的鲁棒性
某些参数设置可能导致无法训练一个或多个数据 folds 。默认情况下,将导致整个搜索失败,即使某些参数设置可以被完全估计。设置error_score=0
(或
=np.NaN
)将使该过程对此类失败具有鲁棒性,发出警告并将该fold的分数设置为0(或
NaN
),但可以完成搜索。
4. 蛮力参数搜索的替代方法
4.1. 模型特定交叉验证
一些模型可以拟合某一参数的一系列数据,其效率几乎与对某个参数的单个值进行估计器拟合的效率相同。利用此功能执行更有效的交叉验证,用于此参数的模型选择。 这个策略最常用的参数是编码正则化器(regularizer)强度的参数。在这种情况下,我们说我们计算估计器的正则化路径(regularization path)。 下面是这些模型的列表:4.2. 信息标准
一些模型可以通过计算单个正则化路径(而不是使用交叉验证时的多个正则化路径)来提供正则化参数最优估计的信息论闭式公式(information-theoretic closed-form formula)。 以下是从 Akaike Information Criterion (AIC) 或 the Bayesian Information Criterion (BIC)中受益的模型列表,用于自动选择模型: 4.3. 袋外估计(Out of Bag Estimates) 当使用基于bagging的集成方法(ensemble methods,即使用带替换进行采样生成新的训练集)时,部分训练集仍然未使用。对于集成(ensemble)中的每个分类器,忽略了训练集的不同部分。 被忽略的部分可用于估计泛化误差,而无需依赖单独的验证集。这个估计是“免费”的,因为不需要额外的数据,并且可以用于模型选择。 这目前在以下类中实现:文壹由“伴编辑器”提供技术支持
☆☆☆为方便大家查阅,小编已将scikit-learn学习路线专栏 文章统一整理到公众号底部菜单栏,同步更新中,关注公众号,点击左下方“系列文章”,如图:
欢迎大家和我一起沿着scikit-learn文档这条路线,一起巩固机器学习算法基础。(添加微信:mthler,备注:sklearn学习,一起进【sklearn机器学习进步群】开启打怪升级的学习之旅。)