3.2. 调整估计器的超参数#

超参数是在估计器中不直接学习的参数。在scikit-learn中,它们作为参数传递给估计器类的构造器。典型的例子包括 C , kernelgamma 对于支持载体分类器, alpha 对于套索等

这是可能的,并建议搜索超参数空间的最佳 cross validation 得分

在构造估计器时提供的任何参数都可以以这种方式优化。具体来说,要查找给定估计器所有参数的名称和当前值,请用途::

estimator.get_params()

搜索包括:

  • 估计器(回归器或分类器, sklearn.svm.SVC() );

  • 参数空间;

  • 搜索或抽样候选人的方法;

  • 交叉验证计划;以及

  • score function .

scikit-learn中提供了两种参数搜索的通用方法:对于给定的值, GridSearchCV 详尽考虑所有参数组合,同时 RandomizedSearchCV 可以从具有指定分布的参数空间中采样给定数量的候选。这两种工具的对应工具连续减半 HalvingGridSearchCVHalvingRandomSearchCV ,这可以更快地找到良好的参数组合。

在描述了这些工具后,我们详细介绍了 best practices 适用于这些方法。某些模型允许专业、高效的参数搜索策略,如中所述 暴力参数搜索的替代方案 .

请注意,这些参数的一小部分可能会对模型的预测或计算性能产生很大影响,而其他参数可能会保留其默认值,这是常见的。建议阅读估计器类的文档字符串,以更好地了解其预期行为,可能通过阅读随附的文献参考来进行。

3.2.2. 随机参数优化#

虽然使用参数设置网格是目前最广泛使用的参数优化方法,但其他搜索方法具有更有利的属性。 RandomizedSearchCV 实现参数随机搜索,其中每个设置都是从可能参数值的分布中采样的。与详尽搜索相比,这有两个主要好处:

  • 可以独立于参数的数量和可能的值来选择预算。

  • 添加不影响性能的参数不会降低效率。

详细说明应如何对参数进行采样是使用字典完成的,与指定参数非常相似 GridSearchCV .此外,计算预算(即采样候选项或采样迭代的数量)是使用 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 , loguniformrandint .

原则上,任何提供 rvs (随机变量样本)对值进行抽样的方法。电话给 rvs 函数应该从连续调用的可能参数值中提供独立的随机样本。

警告

中的分布 scipy.stats scipy 0.16版本之前不允许指定随机状态。相反,它们使用全局numpy随机状态,可以通过 np.random.seed 或使用 np.random.set_state .然而,从scikit-learn 0.18开始, sklearn.model_selection 如果scipy >= 0.16也可用,则模块设置由用户提供的随机状态。

对于连续参数,例如 C 在上述情况下,重要的是指定连续分布以充分利用随机化。通过这种方式, n_iter 总是会导致更好的搜索。

连续的log均匀随机变量是log间隔参数的连续版本。例如,指定相当于 C 从上面看, loguniform(1, 100) 可以用来代替 [1, 10, 100] .

在网格搜索中镜像上面的例子,我们可以指定一个连续随机变量,该变量在之间保持log均匀分布 1e01e3

from sklearn.utils.fixes import loguniform
{'C': loguniform(1e0, 1e3),
 'gamma': loguniform(1e-4, 1e-3),
 'kernel': ['rbf'],
 'class_weight':['balanced', None]}

示例

引用

  • Bergstra,J.和Bengio,Y.,超参数优化的随机搜索,《机器学习研究杂志》(2012年)

3.2.3. 通过连续减半寻找最佳参数#

Scikit-learn还提供 HalvingGridSearchCVHalvingRandomSearchCV 可用于使用连续减半搜索参数空间的估计器 [1] [2] .连续减半(SH)就像候选参数组合之间的锦标赛。SH是一个迭代选择过程,其中在第一次迭代时使用少量资源评估所有候选项(参数组合)。只有其中一些候选人被选择用于下一次迭代,下一次迭代将被分配更多资源。对于参数调优,资源通常是训练样本的数量,但它也可以是任意数字参数,例如 n_estimators 在一片随机的森林中。

备注

选择的资源增加应该足够大,以便在考虑统计显着性时获得分数的大幅提高。

如下图所示,只有一部分候选人“存活”到最后一次迭代。这些候选人在所有迭代中一直排在最高得分的候选人之列。每次迭代都为每个候选者分配越来越多的资源,这里是样本的数量。

../_images/sphx_glr_plot_successive_halving_iterations_001.png

我们在这里简要介绍了主要参数,但每个参数及其相互作用将在下面的第二节中详细描述。的 factor (> 1)参数控制资源增长的速度和候选数量减少的速度。在每次迭代中,每个候选人的资源数量乘以 factor 候选人数除以同一因子。随着 resourcemin_resources , factor 是我们的实现中控制搜索的最重要参数,尽管值3通常效果良好。 factor 有效控制中的迭代次数 HalvingGridSearchCV 以及候选项(默认情况下)和迭代的数量 HalvingRandomSearchCV . aggressive_elimination=True 如果可用资源数量较少,也可以使用。通过调整 min_resources 参数.

这些估计者仍然 experimental :他们的预测和API可能会在没有任何弃用周期的情况下发生变化。要使用它们,您需要显式导入 enable_halving_search_cv

>>> from sklearn.experimental import enable_halving_search_cv  # noqa
>>> from sklearn.model_selection import HalvingGridSearchCV
>>> from sklearn.model_selection import HalvingRandomSearchCV

示例

以下部分深入探讨了连续减半的技术方面。

选择 min_resources 以及候选人数量#

旁边 factor ,影响连续减半搜索行为的两个主要参数是 min_resources 参数以及评估的候选项(或参数组合)的数量。 min_resources 是第一次迭代为每个候选人分配的资源量。候选人数直接在 HalvingRandomSearchCV ,并根据 param_grid 参数 HalvingGridSearchCV .

考虑这样一种情况,其中资源是样本数量,并且我们有1000个样本。理论上,与 min_resources=10factor=2 ,我们能够跑 at most 7次迭代,样本数量如下: [10, 20, 40, 80, 160, 320, 640] .

但根据候选者的数量,我们可能会运行少于7次迭代:如果我们从一个 small 由于候选项的数量,最后一次迭代可能使用少于640个样本,这意味着没有使用所有可用资源(样本)。例如,如果我们从5个候选项开始,我们只需要2次迭代:第一次迭代有5个候选项,然后 5 // 2 = 2 第二次迭代时的候选人,之后我们知道哪个候选人表现最好(所以我们不需要第三个)。我们最多只能使用20个样本,这是一种浪费,因为我们有1000个样本可供使用。另一方面,如果我们从 high 候选人的数量,我们可能会在最后一次迭代中得到很多候选人,这可能并不总是理想的:这意味着许多候选人将使用全部资源运行,基本上将过程减少到标准搜索。

的情况下 HalvingRandomSearchCV ,默认情况下设置候选项的数量,以便最后一次迭代使用尽可能多的可用资源。为 HalvingGridSearchCV ,候选人数由 param_grid 参数.改变的价值 min_resources 将影响可能的迭代次数,因此也将影响候选者的理想数量。

选择时的另一个考虑因素 min_resources 是否容易用少量的资源来区分好的和坏的候选人。例如,如果需要大量样本来区分好参数和坏参数, min_resources 建议。另一方面,如果即使样本量很少,区分也很明显,那么就很小 min_resources 可能是更好的,因为它会加速计算。

请注意,在上面的例子中,最后一次迭代没有使用最大数量的可用资源:有1000个样本可用,但最多只使用了640个样本。默认情况下,两者 HalvingRandomSearchCVHalvingGridSearchCV 尝试在最后一次迭代中使用尽可能多的资源,但限制是资源量必须是两者的倍数 min_resourcesfactor (this在下一节中将清楚地说明这一限制)。 HalvingRandomSearchCV 通过对适量的候选人进行抽样来实现这一目标,而 HalvingGridSearchCV 通过正确设置来实现这一目标 min_resources .

每次迭代中的资源量和候选项数量#

在任何迭代中 i ,每个候选人都被分配了一定数量的资源,我们表示 n_resources_i .该数量由参数控制 factormin_resources 如下 (factor 严格大于1)::

n_resources_i = factor**i * min_resources,

或等效地::

n_resources_{i+1} = n_resources_i * factor

哪里 min_resources == n_resources_0 是第一次迭代使用的资源量。 factor 还定义了下一次迭代将选择的候选人比例::

n_candidates_i = n_candidates // (factor ** i)

或等效地::

n_candidates_0 = n_candidates
n_candidates_{i+1} = n_candidates_i // factor

所以在第一次迭代中,我们使用 min_resources 资源 n_candidates 次在第二次迭代中,我们使用 min_resources * factor 资源 n_candidates // factor 次第三种方法再次乘以每个候选人的资源并划分候选人的数量。当达到每个候选人的最大资源量或当我们确定了最佳候选人时,此过程就会停止。在正在评估的迭代中确定最佳候选人 factor 或更少的候选人(请参阅下面的解释)。

这是一个例子, min_resources=3factor=2 ,从70名候选人开始:

n_resources_i

n_candidates_i

3(=min_resources)

70(=n_候选人)

3 * 2 = 6

70 // 2 = 35

6 * 2 = 12

35 // 2 = 17

12 * 2 = 24

17 // 2 = 8

24 * 2 = 48

8 // 2 = 4

48 * 2 = 96

4 // 2 = 2

我们可以注意到:

  • 该过程在第一次迭代时停止,该迭代评估 factor=2 候选人:最好的候选人是这2名候选人中最好的。没有必要运行额外的迭代,因为它只会评估一个候选人(即我们已经确定的最佳候选人)。出于这个原因,一般来说,我们希望最后一次迭代最多运行 factor 候选人如果最后一次迭代的评估结果超过 factor 候选者,然后最后一次迭代简化为常规搜索(如 RandomizedSearchCVGridSearchCV ).

  • 每个 n_resources_i 是两者的倍数 factormin_resources (这通过上面的定义得到了证实)。

每次迭代使用的资源量可以在 n_resources_ 属性

选择资源#

默认情况下,资源根据样本数量定义。也就是说,每次迭代都会使用越来越多的样本进行训练。但是,您可以手动指定一个参数,用作 resource 参数.以下是一个示例,其中资源是根据随机森林的估计量数量定义的::

>>> from sklearn.datasets import make_classification
>>> from sklearn.ensemble import RandomForestClassifier
>>> from sklearn.experimental import enable_halving_search_cv  # noqa
>>> from sklearn.model_selection import HalvingGridSearchCV
>>> import pandas as pd
>>> param_grid = {'max_depth': [3, 5, 10],
...               'min_samples_split': [2, 5, 10]}
>>> base_estimator = RandomForestClassifier(random_state=0)
>>> X, y = make_classification(n_samples=1000, random_state=0)
>>> sh = HalvingGridSearchCV(base_estimator, param_grid, cv=5,
...                          factor=2, resource='n_estimators',
...                          max_resources=30).fit(X, y)
>>> sh.best_estimator_
RandomForestClassifier(max_depth=5, n_estimators=24, random_state=0)

请注意,不可能对属于参数网格一部分的参数进行预算。

耗尽可用资源#

如上所述,每次迭代使用的资源数量取决于 min_resources 参数.如果您有很多可用资源,但一开始的资源数量很少,则其中一些可能会被浪费(即未使用)::

>>> from sklearn.datasets import make_classification
>>> from sklearn.svm import SVC
>>> from sklearn.experimental import enable_halving_search_cv  # noqa
>>> from sklearn.model_selection import HalvingGridSearchCV
>>> import pandas as pd
>>> param_grid= {'kernel': ('linear', 'rbf'),
...              'C': [1, 10, 100]}
>>> base_estimator = SVC(gamma='scale')
>>> X, y = make_classification(n_samples=1000)
>>> sh = HalvingGridSearchCV(base_estimator, param_grid, cv=5,
...                          factor=2, min_resources=20).fit(X, y)
>>> sh.n_resources_
[20, 40, 80]

搜索过程最多只会使用80个资源,而我们的最大可用资源量是 n_samples=1000 .这里有 min_resources = r_0 = 20 .

HalvingGridSearchCV ,默认情况下, min_resources 参数设置为“exhaust”。这意味着 min_resources 被自动设置,以便最后一次迭代可以在 max_resources 限制::

>>> sh = HalvingGridSearchCV(base_estimator, param_grid, cv=5,
...                          factor=2, min_resources='exhaust').fit(X, y)
>>> sh.n_resources_
[250, 500, 1000]

min_resources 在这里被自动设置为250,这会导致使用所有资源的最后一次迭代。使用的确切值取决于候选参数的数量, max_resourcesfactor .

HalvingRandomSearchCV ,可以通过两种方式耗尽资源:

  • 通过设置 min_resources='exhaust' ,就像 HalvingGridSearchCV ;

  • 通过设置 n_candidates='exhaust' .

这两种选择是相互排斥的:使用 min_resources='exhaust' 需要了解候选人的数量,并且对称 n_candidates='exhaust' 需要知道 min_resources .

一般来说,耗尽资源总数会得到更好的最终候选参数,并且时间稍微密集一些。

3.2.3.1. 积极淘汰候选人#

使用 aggressive_elimination 参数,您可以强制搜索过程最终得到少于 factor 最后一次迭代的候选人。

主动消除的代码示例#

理想情况下,我们希望最后一次迭代进行评估 factor 候选人然后我们只需要选择最好的。当可用资源的数量相对于候选数量较小时,最后一次迭代可能必须评估超过 factor 候选人::

>>> from sklearn.datasets import make_classification
>>> from sklearn.svm import SVC
>>> from sklearn.experimental import enable_halving_search_cv  # noqa
>>> from sklearn.model_selection import HalvingGridSearchCV
>>> import pandas as pd
>>> param_grid = {'kernel': ('linear', 'rbf'),
...               'C': [1, 10, 100]}
>>> base_estimator = SVC(gamma='scale')
>>> X, y = make_classification(n_samples=1000)
>>> sh = HalvingGridSearchCV(base_estimator, param_grid, cv=5,
...                          factor=2, max_resources=40,
...                          aggressive_elimination=False).fit(X, y)
>>> sh.n_resources_
[20, 40]
>>> sh.n_candidates_
[6, 3]

由于我们不能使用超过 max_resources=40 资源,流程必须停止在第二次迭代,该迭代评估超过 factor=2 候选人

当使用 aggressive_elimination ,该过程将使用必要的方法消除尽可能多的候选人 min_resources 资源::

>>> sh = HalvingGridSearchCV(base_estimator, param_grid, cv=5,
...                            factor=2,
...                            max_resources=40,
...                            aggressive_elimination=True,
...                            ).fit(X, y)
>>> sh.n_resources_
[20, 20, 40]
>>> sh.n_candidates_
[6, 3, 2]

请注意,我们在最后一次迭代中以2个候选项结束,因为我们在第一次迭代中已经消除了足够的候选项,使用 n_resources = min_resources = 20 .

3.2.3.2. 使用分析结果 cv_results_ 属性#

cv_results_ 属性包含用于分析搜索结果的有用信息。它可以改造成熊猫摇篮, df = pd.DataFrame(est.cv_results_) .的 cv_results_ 属性 HalvingGridSearchCVHalvingRandomSearchCV 类似于 GridSearchCVRandomizedSearchCV ,以及与连续减半过程相关的额外信息。

(截短的)输出收件箱示例:#

ITER

n_resources

mean_test_score

params

0

0

125

0.983667

“标准”:“log_loss”,“max_depth”:无,“max_features”:9,“min_samples_split”:5}

1

0

125

0.983667

“标准”:“gini”,“max_depth”:无,“max_features”:8,“min_samples_split”:7}

2

0

125

0.983667

“标准”:“gini”,“max_depth”:无,“max_features”:10,“min_samples_split”:10}

3

0

125

0.983667

“criteria”:“log_loss”,“max_depth”:无,“max_features”:6,“min_samples_split”:6}

...

...

...

...

...

15

2

500

0.951958

“标准”:“log_loss”,“max_depth”:无,“max_features”:9,“min_samples_split”:10}

16

2

500

0.947958

“标准”:“gini”,“max_depth”:无,“max_features”:10,“min_samples_split”:10}

17

2

500

0.951958

“标准”:“gini”,“max_depth”:无,“max_features”:10,“min_samples_split”:4}

18

3

1000

0.961009

“标准”:“log_loss”,“max_depth”:无,“max_features”:9,“min_samples_split”:10}

19

3

1000

0.955989

“标准”:“gini”,“max_depth”:无,“max_features”:10,“min_samples_split”:4}

每一行对应于给定的参数组合(候选)和给定的迭代。迭代由 iter 柱的 n_resources 列告诉您使用了多少资源。

在上面的例子中,最佳的参数组合是 {'criterion': 'log_loss', 'max_depth': None, 'max_features': 9, 'min_samples_split': 10} 因为它已经达到了最高分数的最后一次迭代(3):0.96。

引用