☰
auto-sklearn 组件扩展指南:编写并注册自定义分类器、回归器与特征预处理器
2026/9/26 2:28:31 网站建设 项目流程
  • 人工智能
  • AutoML
  • 机器学习

【免费下载链接】auto-sklearn

Automated Machine Learning with scikit-learn

项目地址:https://gitcode.com/gh_mirrors/au/auto-sklearn
点击查看免费下载

auto-sklearn 基于 scikit-learn 生态,其自动化能力建立在"组件(component)"体系之上:每个分类器、回归器或预处理器都被包装成一个组件,纳入统一的配置空间搜索。本文基于仓库文档 doc/extending.rst,完整讲解如何编写自定义组件(wrapper class)、定义其超参数搜索空间与数据属性,并通过注册 API 将组件接入 auto-sklearn,最后结合仓库源码与 examples/80_extending 目录下的可运行示例给出可直接复用的实战方案。

读完本文,你将掌握:三种组件基类(分类、回归、预处理)的抽象接口、get_hyperparameter_search_space()与get_properties()的完整契约、add_classifier/add_regressor/add_preprocessor注册函数的用法,以及如何通过include/exclude参数控制搜索空间中的可用组件。

扩展机制总览

auto-sklearn 可以被非常容易地扩展出新的分类(classification)、回归(regression)和特征预处理(feature preprocessing)方法。整个过程分为两步:

  1. 实现一个 wrapper 类:把现有的机器学习模型(或你自己实现的算法)包装成组件,并实现 auto-sklearn 所需的接口;
  2. 注册组件:通过对应的注册函数告诉 auto-sklearn 该组件的存在,使其进入配置空间参与搜索。

这种设计让 auto-sklearn 的核心搜索机制(SMAC 优化、成功减半、集成构建等)完全复用,你只需要关注"模型本身"。从源码看,注册的组件会统一进入一个全局注册表_addons,并与内置组件一起参与候选构建(见 autosklearn/pipeline/components/base.py)。

选择正确的基类

根据组件的用途,它必须是以下三个基类之一的子类:

用途基类所在模块
分类器AutoSklearnClassificationAlgorithmautosklearn/pipeline/components/base.py
回归器AutoSklearnRegressionAlgorithmautosklearn/pipeline/components/base.py
预处理器AutoSklearnPreprocessingAlgorithmautosklearn/pipeline/components/base.py

这些基类本质上是"现有机器学习模型的包装器",只是额外补充了 auto-sklearn 需要的功能。当然,你也可以直接在组件内部实现一个全新的机器学习算法。

三个基类都继承自AutoSklearnComponent(它又继承自 scikit-learn 的BaseEstimator),因此自定义组件天然具备set_hyperparameters()能力:配置空间中的每个超参数会通过configuration.get_dictionary()读取并以setattr方式注入组件实例(见 autosklearn/pipeline/components/base.py)。这意味着你的__init__参数名必须与配置空间中的超参数名一一对应。

每个组件必须实现三类接口:

  • 返回配置空间的方法:get_hyperparameter_search_space();
  • 查询组件属性的方法:get_properties();
  • 任务相关方法:分类/回归器实现fit()与predict(),预处理器实现fit()与transform()。

以下分别详细说明。

定义超参数搜索空间:get_hyperparameter_search_space()

该方法返回一个ConfigSpace.configuration_space.ConfigurationSpace实例,它描述了该组件所有可调超参数及其取值范围、分布类型和默认值。

三个基类的抽象定义可参考:

  • AutoSklearnClassificationAlgorithm.get_hyperparameter_search_space()
  • AutoSklearnRegressionAlgorithm.get_hyperparameter_search_space()
  • AutoSklearnPreprocessingAlgorithm.get_hyperparameter_search_space()

方法签名统一为get_hyperparameter_search_space(feat_type=None, dataset_properties=None),其中feat_type描述特征类型(如数值、类别、文本),dataset_properties描述数据集属性(如是否稀疏、是否为多分类),二者都可作为构建条件化配置空间的依据(见 autosklearn/pipeline/components/base.py)。

以仓库示例中的 MLP 分类器为例(examples/80_extending/example_extending_classification.py):

from ConfigSpace.configuration_space import ConfigurationSpace from ConfigSpace.hyperparameters import ( CategoricalHyperparameter, UniformIntegerHyperparameter, UniformFloatHyperparameter, ) @staticmethod def get_hyperparameter_search_space(feat_type=None, dataset_properties=None): cs = ConfigurationSpace() hidden_layer_depth = UniformIntegerHyperparameter( name="hidden_layer_depth", lower=1, upper=3, default_value=1 ) num_nodes_per_layer = UniformIntegerHyperparameter( name="num_nodes_per_layer", lower=16, upper=216, default_value=32 ) activation = CategoricalHyperparameter( name="activation", choices=["identity", "logistic", "tanh", "relu"], default_value="relu", ) alpha = UniformFloatHyperparameter( name="alpha", lower=0.0001, upper=1.0, default_value=0.0001 ) solver = CategoricalHyperparameter( name="solver", choices=["lbfgs", "sgd", "adam"], default_value="adam" ) cs.add_hyperparameters( [hidden_layer_depth, num_nodes_per_layer, activation, alpha, solver] ) return cs

配置空间还支持条件依赖:即某些超参数只有在另一些超参数取特定值时才生效。例如回归示例中,degree和coef0仅在kernel == "polynomial"时才有意义(examples/80_extending/example_extending_regression.py):

from ConfigSpace.conditions import EqualsCondition degree_condition = EqualsCondition(degree, kernel, "polynomial") coef0_condition = EqualsCondition(coef0, kernel, "polynomial") cs.add_conditions([degree_condition, coef0_condition])

预处理器示例中则用InCondition实现"shrinkage仅在solver为 lsqr/eigen 时生效"(examples/80_extending/example_extending_preprocessor.py)。

关于如何创建ConfigurationSpace对象的更多细节,可参考仓库中autosklearn/pipeline/components/classification/、regression/、feature_preprocessing/等目录下内置组件的源码,它们是最佳的参照实现。

声明组件能力:get_properties()

该方法返回一个字典,描述该组件在构建机器学习流水线时能被如何使用。以下字段必须全部指定(字段集合由ThirdPartyComponents.add_component()强制校验,见 autosklearn/pipeline/components/base.py):

字段类型含义
shortnamestr组件的缩写
namestr组件的完整名称
handles_regressionbool是否能处理回归数据
handles_classificationbool是否能处理分类数据
handles_multiclassbool是否能处理多分类数据
handles_multilabelbool是否能处理多标签分类数据
is_deterministicbool在相同随机种子下多次运行是否给出相同结果

注意:仓库源码还额外要求handles_multioutput字段(见 autosklearn/pipeline/components/base.py),回归与特征预处理的组件选择逻辑也会读取它(autosklearn/pipeline/components/regression/init.py)。编写自定义组件时请一并提供。

input与output字段

这两个字段是元组,声明组件接受和产生的数据类型,取值使用 autosklearn/pipeline/constants.py 中定义的常量:

input(组件能处理的数据类型,可包含多个值)

  • autosklearn.constants.DENSE:稠密数据数组,与SPARSE互斥;
  • autosklearn.constants.SPARSE:稀疏数据矩阵,与DENSE互斥;
  • autosklearn.constants.UNSIGNED_DATA:无符号数据(仅正输入),与SIGNED_DATA互斥;
  • autosklearn.constants.SIGNED_DATA:有符号数据(同时包含正负输入值),与UNSIGNED_DATA互斥。

output(组件输出的数据类型)

  • autosklearn.constants.PREDICTIONS:预测结果,例如分类器的输出;
  • autosklearn.constants.INPUT:与输入同形式的数据;
  • autosklearn.constants.DENSE:稠密数据数组,与SPARSE互斥;声明后稀疏数据会被转换为稠密表示;
  • autosklearn.constants.SPARSE:稀疏数据矩阵,与DENSE互斥;声明后稠密数据会被转换为稀疏表示;
  • autosklearn.constants.UNSIGNED_DATA:无符号数据,与SIGNED_DATA互斥;允许只能处理正数据的算法使用;
  • autosklearn.constants.SIGNED_DATA:有符号数据,与UNSIGNED_DATA互斥。

需要注意的是,在导入时这些常量可以从autosklearn.pipeline.constants导入(示例代码中使用的是from autosklearn.pipeline.constants import DENSE, SPARSE, ...),而文档中引用的是autosklearn.constants命名空间——两者指向同一组数值常量(见 autosklearn/pipeline/constants.py)。

以 LDA 预处理器为例(examples/80_extending/example_extending_preprocessor.py):

@staticmethod def get_properties(dataset_properties=None): return { "shortname": "LDA", "name": "Linear Discriminant Analysis", "handles_regression": False, "handles_classification": True, "handles_multiclass": False, "handles_multilabel": False, "handles_multioutput": False, "is_deterministic": True, "input": (DENSE, UNSIGNED_DATA, SIGNED_DATA), "output": (DENSE, UNSIGNED_DATA, SIGNED_DATA), }

get_properties()在组件选择时会被高频调用:auto-sklearn 会依据数据集属性(稀疏与否、是否多分类/多标签/多输出、目标任务类型等)过滤掉不合适的组件。例如AutoSklearnChoice.get_available_components()会在数据集为稀疏时剔除input中不含SPARSE的组件(见 autosklearn/pipeline/components/base.py);ClassifierChoice则依据handles_classification/handles_multiclass/handles_multilabel过滤(autosklearn/pipeline/components/classification/init.py)。因此属性声明不准确会导致组件被静默排除或产生错误结果。

注册组件:告诉 auto-sklearn 组件存在

编写完组件类后,需要按组件类型调用以下注册函数:

  • 分类器:autosklearn.pipeline.components.classification.add_classifier()
  • 回归器:autosklearn.pipeline.components.regression.add_regressor()
  • 预处理器:autosklearn.pipeline.components.feature_preprocessing.add_preprocessor()

三者都是对ThirdPartyComponents.add_component()的薄封装。以add_classifier为例:

from typing import Type from autosklearn.pipeline.components.base import AutoSklearnClassificationAlgorithm additional_components = ThirdPartyComponents(AutoSklearnClassificationAlgorithm) _addons["classification"] = additional_components def add_classifier(classifier: Type[AutoSklearnClassificationAlgorithm]) -> None: additional_components.add_component(classifier)

add_component()会做两件事(见 autosklearn/pipeline/components/base.py):

  1. 类型校验:传入对象必须是base_class的直接子类,否则抛出TypeError;
  2. 属性校验:检查get_properties()返回的键集合——既不允许出现不在白名单中的多余属性,也不允许缺失shortname、name、handles_regression、handles_classification、handles_multiclass、handles_multilabel、handles_multioutput、is_deterministic、input、output中的任何一项,否则抛出ValueError。

注册后,组件会存入ThirdPartyComponents.components(一个有序字典),并在构建配置空间时通过ClassifierChoice.get_components()/RegressorChoice.get_components()/FeaturePreprocessorChoice.get_components()与内置组件合并(autosklearn/pipeline/components/classification/init.py)。每个组件还会以自身名字作为条件分支挂入顶层__choice__分类超参数(autosklearn/pipeline/components/classification/init.py),从而实现"组件间选择 + 组件内调参"的两级搜索空间结构。

内置组件的自动发现

除了add_*注册,仓库还提供了一条自动发现路径:find_components()会遍历组件目录中的每个 Python 模块,凡是直接继承基类的类都会被自动收集(见 autosklearn/pipeline/components/base.py)。这意味着把新组件文件放进autosklearn/pipeline/components/classification/、regression/或feature_preprocessing/目录即可被自动加载。对于第三方扩展,add_*系列 API 是更干净、不侵入源码树的方式。

编写分类组件

在get_properties()和get_hyperparameter_search_space()之外,分类组件还需实现fit(X, y)和predict(X),它们是 scikit-learn predictor API 的实现。此外,分类器通常还应实现predict_proba(X)以支持概率输出(集成与部分评价指标依赖它)。

仓库中AutoSklearnClassificationAlgorithm的抽象接口(见 autosklearn/pipeline/components/base.py)要求:组件内部持有底层估计器self.estimator,并通过get_estimator()返回。MLP 分类器示例的完整骨架(examples/80_extending/example_extending_classification.py):

from autosklearn.pipeline.components.base import AutoSklearnClassificationAlgorithm class MLPClassifier(AutoSklearnClassificationAlgorithm): def __init__(self, hidden_layer_depth, num_nodes_per_layer, activation, alpha, solver, random_state=None): self.hidden_layer_depth = hidden_layer_depth self.num_nodes_per_layer = num_nodes_per_layer self.activation = activation self.alpha = alpha self.solver = solver self.random_state = random_state def fit(self, X, y): # 将配置空间中的超参数转换为底层模型的参数 self.num_nodes_per_layer = int(self.num_nodes_per_layer) self.hidden_layer_depth = int(self.hidden_layer_depth) self.alpha = float(self.alpha) from sklearn.neural_network import MLPClassifier hidden_layer_sizes = tuple( self.num_nodes_per_layer for i in range(self.hidden_layer_depth) ) self.estimator = MLPClassifier( hidden_layer_sizes=hidden_layer_sizes, activation=self.activation, alpha=self.alpha, solver=self.solver, random_state=self.random_state, ) self.estimator.fit(X, y) return self def predict(self, X): if self.estimator is None: raise NotImplementedError() return self.estimator.predict(X) def predict_proba(self, X): if self.estimator is None: raise NotImplementedError() return self.estimator.predict_proba(X)

注册并启用:

import autosklearn.pipeline.components.classification autosklearn.pipeline.components.classification.add_classifier(MLPClassifier) clf = autosklearn.classification.AutoSklearnClassifier( time_left_for_this_task=30, per_run_time_limit=10, include={"classifier": ["MLPClassifier"]}, initial_configurations_via_metalearning=0, smac_scenario_args={"runcount_limit": 5}, ) clf.fit(X_train, y_train)

include将搜索空间限定为你注册的组件;initial_configurations_via_metalearning=0与smac_scenario_args={"runcount_limit": 5}仅用于加速示例运行,真实场景不建议照搬。

编写回归组件

回归组件在get_properties()和get_hyperparameter_search_space()之外,需实现fit(X, y)和predict(X),同样遵循 scikit-learn predictor API。抽象接口定义在AutoSklearnRegressionAlgorithm(autosklearn/pipeline/components/base.py)。

仓库中的核岭回归(KernelRidgeRegression)示例(examples/80_extending/example_extending_regression.py)展示了完整写法,其中值得关注的点:

  • input声明为(SPARSE, DENSE, UNSIGNED_DATA, SIGNED_DATA),output为(PREDICTIONS,),表明该回归器同时兼容稠密与稀疏输入;
  • 使用log=True的UniformFloatHyperparameter在对数尺度上搜索alpha、gamma、coef0(这些超参数数量级跨度大);
  • 通过EqualsCondition让degree、coef0只在kernel == "polynomial"时被激活。

注册与启用方式:

import autosklearn.regression import autosklearn.pipeline.components.regression autosklearn.pipeline.components.regression.add_regressor(KernelRidgeRegression) reg = autosklearn.regression.AutoSklearnRegressor( time_left_for_this_task=30, per_run_time_limit=10, include={"regressor": ["KernelRidgeRegression"]}, initial_configurations_via_metalearning=0, smac_scenario_args={"runcount_limit": 5}, ) reg.fit(X_train, y_train)

编写特征预处理器

特征预处理器在get_properties()和get_hyperparameter_search_space()之外,需实现fit(X, y=None)和transform(X),同样是 scikit-learn transformer 风格(抽象定义见 autosklearn/pipeline/components/base.py)。注意预处理器内部持有的是self.preprocessor而非self.estimator,通过get_preprocessor()返回。

LDA 预处理器示例(examples/80_extending/example_extending_preprocessor.py):

class LDA(AutoSklearnPreprocessingAlgorithm): def __init__(self, solver, tol, shrinkage=None, random_state=None): self.solver = solver self.shrinkage = shrinkage self.tol = tol self.random_state = random_state self.preprocessor = None def fit(self, X, y=None): if check_none(self.shrinkage): self.shrinkage = None else: self.shrinkage = float(self.shrinkage) self.tol = float(self.tol) import sklearn.discriminant_analysis self.preprocessor = sklearn.discriminant_analysis.LinearDiscriminantAnalysis( shrinkage=self.shrinkage, solver=self.solver, tol=self.tol, ) self.preprocessor.fit(X, y) return self def transform(self, X): if self.preprocessor is None: raise NotImplementedError() return self.preprocessor.transform(X)

注册并在分类任务中强制使用该预处理器:

import autosklearn.pipeline.components.feature_preprocessing autosklearn.pipeline.components.feature_preprocessing.add_preprocessor(LDA) clf = autosklearn.classification.AutoSklearnClassifier( time_left_for_this_task=30, include={"feature_preprocessor": ["LDA"]}, initial_configurations_via_metalearning=0, smac_scenario_args={"runcount_limit": 5}, ) clf.fit(X_train, y_train)

FeaturePreprocessorChoice.get_available_components()会依据dataset_properties["target_type"]分别检查分类/回归相关属性(autosklearn/pipeline/components/feature_preprocessing/init.py),所以预处理器必须正确声明handles_classification/handles_regression等字段,否则会被过滤。

数据预处理器(data preprocessor)的扩展入口

除特征预处理器外,auto-sklearn 还有独立的"数据预处理器"(data preprocessing)阶段,其注册入口是autosklearn.pipeline.components.data_preprocessing.add_preprocessor()。仓库示例 example_extending_data_preprocessor.py 用这一入口实现了一个NoPreprocessing组件(fit原样返回自身、transform直接返回输入),配合include={"data_preprocessor": ["NoPreprocessing"]}即可完全关闭默认的数据预处理步骤。这类组件的output应声明为(INPUT,),表示输出与输入同形式。

限制现有组件的超参数:子类化复用

除了从零编写组件,还可以子类化内置组件来收紧或改写其超参数空间。仓库示例 example_restrict_number_of_hyperparameters.py 演示了这一点:CustomRandomForest继承AutoSklearnClassificationAlgorithm,只暴露n_estimators与max_features两个超参数(内置random_forest则调参更多),注册后通过exclude={"classifier": ["random_forest"]}排除内置随机森林,再用clf.get_configuration_space(X_train, y_train)断言配置空间中已不再包含random_forest:

clf = autosklearn.classification.AutoSklearnClassifier( time_left_for_this_task=30, per_run_time_limit=10, exclude={"classifier": ["random_forest"]}, initial_configurations_via_metalearning=0, smac_scenario_args={"runcount_limit": 1}, ) clf.fit(X_train, y_train) cs = clf.get_configuration_space(X_train, y_train) assert "random_forest" not in str(cs)

这里体现了include/exclude与注册机制的组合用法:include精确指定要用的组件(键为classifier/regressor/feature_preprocessor/data_preprocessor,值为组件类名列表),exclude则剔除指定组件,二者不能同时使用(见 autosklearn/automl.py 的参数定义与各get_available_components()中的互斥校验)。

组件是如何被接入流水线的

理解底层接线有助于调试扩展问题。以分类器为例(autosklearn/pipeline/components/classification/init.py):

  1. ClassifierChoice.get_hyperparameter_search_space()先调用get_available_components()(基于get_properties()声明与数据集属性过滤候选);
  2. 创建顶层分类超参数__choice__,默认值按random_forest→liblinear_svc→sgd→libsvm_svc的优先级从可用组件中选取;
  3. 为每个候选组件调用其get_hyperparameter_search_space(),并以parent_hyperparameter挂载为__choice__的条件分支,形成嵌套配置空间;
  4. 搜索到具体配置后,AutoSklearnChoice.set_hyperparameters()解析__choice__并实例化对应组件,把带前缀的超参数名还原后传入构造器(autosklearn/pipeline/components/base.py)。

因此,自定义组件的__init__参数名、get_hyperparameter_search_space()中的超参数名、get_properties()声明必须保持严格一致,且属性声明必须真实反映组件能力——任何一个环节不匹配,都会导致组件被过滤、实例化失败或运行期报错。

快速自查清单

编写并注册一个组件时,建议逐项核对:

  1. 基类选择正确:分类/回归/预处理分别继承对应的AutoSklearn*Algorithm;
  2. get_hyperparameter_search_space()返回合法ConfigurationSpace,超参数名与__init__参数一致;
  3. get_properties()包含全部必填字段(含handles_multioutput),input/output使用DENSE/SPARSE/PREDICTIONS/INPUT/SIGNED_DATA/UNSIGNED_DATA常量;
  4. 分类器实现fit/predict(建议同时实现predict_proba),回归器实现fit/predict,预处理器实现fit/transform,均返回self且符合 scikit-learn API 约定;
  5. 调用对应的add_classifier/add_regressor/add_preprocessor完成注册;
  6. 通过include/exclude验证组件确实进入(或退出)了搜索空间,可借助get_configuration_space()打印确认。

完成以上步骤后,你的自定义模型就能像内置组件一样,被 auto-sklearn 的元学习、贝叶斯优化(SMAC)、成功减半与集成构建等整套机制驱动,参与到自动化机器学习流水线的搜索与评估中。

  • 人工智能
  • AutoML
  • 机器学习

【免费下载链接】auto-sklearn

Automated Machine Learning with scikit-learn

项目地址:https://gitcode.com/gh_mirrors/au/auto-sklearn
点击查看免费下载

相关推荐

上一篇:无需Caffe!5分钟掌握OpenCV dnn_objdetect模块ONNX目标检测部署 🚀
下一篇:ip2region 快速入门:3 分钟搭出 10 微秒级离线 IP 定位

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询