清风的技术小屋

不为所动, 做更专业的自己

0%

ConfigSpace备忘录

介绍

ConfigSpace是一个用于管理算法参数空间的Python包,主要用于算法参数选择任务。一些AutoML库,例如SMAC3BOHB以及auto-sklearn,会用到该包。项目主页为:https://github.com/automl/ConfigSpace

注明:本文章相关代码在Gist

初始化

使用ConfigSpace包时通常要创建一个参数空间实例

1
2
3
4
import ConfigSpace as CS
import ConfigSpace.hyperparameters as CSH

cs = CS.ConfigurationSpace()

这个参数空间集合实例cs包含所有参数的设置

整数参数和浮点参数

本节开始将介绍如何配置算法的参数空间,这里举例的算法为SVM分类算法,算法具体实现为sklearn.svm.SVC。由SVC类介绍可以知道两个参数:

  1. C为惩罚参数,数据类型为浮点数,且\(C \ge 0\)
  2. max_iter为最大迭代次数,数据类型为整数

假设要限定C的取值范围为\([0, 1]\)以及max_iter的取值范围为\([10, 100]\),可以用UniformFloatHyperparameterUniformIntegerHyperparameter设定参数范围

1
2
param_c = CSH.UniformFloatHyperparameter(name='C', lower=0, upper=1)
param_max_iter = CSH.UniformIntegerHyperparameter(name='max_iter', lower=10, upper=100)

设定完参数空间后,需要添加到参数空间集合实例cs

1
2
cs.add_hyperparameter(param_c)
cs.add_hyperparameter(param_max_iter)

此时可以使用cssample_configuration方法进行采样获得一组随机的参数

1
cs.sample_configuration()

此时输出类似下面这种情况

1
2
3
Configuration:
C, Value: 0.7114185317566737
max_iter, Value: 84

Categorical参数和参数之间的联系

sklearn.svm.SVC类介绍可知,算法核类型由参数kernel控制

  • kernel限定算法的核类型,取值主要有'linear''poly''rbf''sigmoid'

此时可以用CategoricalHyperparameter来代表参数kernel

1
2
3
param_kernel = CSH.CategoricalHyperparameter(name='kernel', choices=['linear', 'poly', 'rbf', 'sigmoid'])

cs.add_hyperparameter(param_kernel)

每一种核还有相应的参数设置(设定SVC类对应的参数),即

  • Linear核\(K(x, y)=x^Ty\),无参数
  • Poly核\(K(x, y)=(\gamma x^Ty + r)^d\),其中参数\(\gamma\)对应gamma,参数\(r\)对应coef0,参数\(d\)对应degree
  • RBF核\(K(x, y)=\exp(-\gamma \Vert x - y\Vert^2)\),其中参数\(\gamma\)对应gamma
  • Sigmoid核\(K(x, y)=\tanh(\gamma x^T y + r)\),其中参数\(\gamma\)对应gamma,参数\(r\)对应coef0

首先创建参数degreecoef0以及gamma的参数空间

1
2
3
4
5
param_degree = CSH.UniformIntegerHyperparameter(name='degree', lower=2, upper=4)
param_coef0 = CSH.UniformFloatHyperparameter(name='coef0', lower=0, upper=1)
param_gamma = CSH.UniformFloatHyperparameter(name='gamma', lower=1e-5, upper=1e2)

cs.add_hyperparameters([param_degree, param_coef0, param_gamma])

有前面的描述可以知道不同的核对应不同的参数,也就是说核参数和核类型参数之间是由关联的

  • 参数degree关联Poly核
  • 参数coef0关联Poly核和Sigmoid核
  • 参数gamma关联Poly核、RBF核和Sigmoid核

要想表示这种参数之间的关系,可以使用EqualsCondition以及OrConjunction,即

1
2
3
4
5
6
7
8
cond1 = CS.EqualsCondition(param_degree, param_kernel, 'poly')
cond2 = CS.OrConjunction(CS.EqualsCondition(param_coef0, param_kernel, 'poly'),
CS.EqualsCondition(param_coef0, param_kernel, 'sigmoid'))
cond3 = CS.OrConjunction(CS.EqualsCondition(param_gamma, param_kernel, 'rbf'),
CS.EqualsCondition(param_gamma, param_kernel, 'poly'),
CS.EqualsCondition(param_gamma, param_kernel, 'sigmoid'))

cs.add_conditions([cond1, cond2, cond3])

其中

1
CS.EqualsCondition(param_degree, param_kernel, 'poly')

意思为参数kernel值为'poly'时,设定参数degree的值。如果有多个条件,需要用OrConjunction来OR这些条件

1
2
cond2 = CS.OrConjunction(CS.EqualsCondition(param_coef0, param_kernel, 'poly'),
CS.EqualsCondition(param_coef0, param_kernel, 'sigmoid'))

意思为当参数kernel值为'poly'时,设定参数coef0值,或者当参数kernel值为'sigmoid'时,设定参数coef0值。

禁止参数取值组合出现

前面我们设定了sklearn.svm.SVC类某些参数的参数空间,假如SVC的核选择的是Linear核,即参数kernel取值为'Linear',此时SVM变成了LinearSVM。如果SVC类的LinearSVM实现为sklearn.svm.LinearSVC,这时可以用LinearSVC类参数进一步控制算法的运行过程。 注:这里只是假设一种情况,即SVC类有LinearSVC类的全部参数,真实情况是SVC类并没有LinearSVC类的全部参数。

LinearSVC类部分参数如下

  • penalty设置正则项类型,数据类型为字符串,取值为'l1'或者'l2'
  • loss设置损失函数类型,数据类型为字符串,取值为'hinge'或者'squared_hinge'
  • dual设置算法是否求解对偶问题,数据类型为布尔值,实际可以替换成字符串类型

首先根据这三个参数设置参数空间

1
2
3
4
5
param_penalty = CSH.CategoricalHyperparameter(name='penalty', choices=['l1', 'l2'], default_value='l2')
param_loss = CSH.CategoricalHyperparameter(name='loss', choices=['hinge', 'squared_hinge'], default_value='squared_hinge')
param_dual = CSH.CategoricalHyperparameter(name='dual', choices=['True','False'], default_value='False')

cs.add_hyperparameters([param_penalty, param_loss, param_dual])

当核类型为Linear核时,这三个参数才会被设置,因此要进行参数关联

1
2
3
4
5
cond1 = CS.EqualsCondition(param_penalty, param_kernel, 'linear')
cond2 = CS.EqualsCondition(param_loss, param_kernel, 'linear')
cond3 = CS.EqualsCondition(param_dual, param_kernel, 'linear')

cs.add_conditions([cond1, cond2, cond3])

这里限定一些参数组合不能出现

  • 参数penalty取值'l1',参数loss取值'hinge'
  • 参数dual取值'False',参数penalty取值'l2',参数loss取值'hinge'
  • 参数dual取值'False',参数'penalty'取值'l1'

要禁止出现某些参数组合,可以使用ForbiddenEqualsClause,如果有多个组合,需要使用ForbiddenAndConjunction进行OR

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
penalty_loss = CS.ForbiddenAndConjunction(
CS.ForbiddenEqualsClause(param_penalty, 'l2'),
CS.ForbiddenEqualsClause(param_loss, 'hinge')
)
dual_penalty_loss = CS.ForbiddenAndConjunction(
CS.ForbiddenEqualsClause(param_dual, 'False'),
CS.ForbiddenEqualsClause(param_penalty, 'l2'),
CS.ForbiddenEqualsClause(param_loss, 'hinge')
)

penalty_dual = CS.ForbiddenAndConjunction(
CS.ForbiddenEqualsClause(param_dual, 'False'),
CS.ForbiddenEqualsClause(param_penalty, 'l1')
)

cs.add_forbidden_clause(penalty_loss)
cs.add_forbidden_clause(dual_penalty_loss)
cs.add_forbidden_clause(penalty_dual)