AutoML-第六章-Auto-sklearn

介绍了Auto-sklearn,一种高效的自动化机器学习系统,它基于Python机器学习包scikit-learn。该系统能够自动选择合适的算法和预处理步骤,并调整超参数,显著提升了自动机器学习的效率和鲁棒性。

第六章:Auto-sklearn: 高效和鲁棒的自动化机器学习

摘要

机器学习在各种应用中的成功导致对机器学习系统的需求不断增长,这些机器学习系统可以由非专家立即使用。为了在实践中有效,此类系统需要自动为手头的新数据集选择良好的算法和特征预处理步骤,并设置其各自的超参数。借助有效的贝叶斯优化方法,最近的工作已开始解决这种自动机器学习(AutoML)问题。在此基础上,我们引入了一个基于 Python 机器学习包 scikit-learn 的强大的新 AutoML 系统(使用 15 个分类器,14 个特征预处理方法和 4 种数据预处理方法,从而产生具有 110 个超参数的结构化假设空间)。我们将此系统称为 Auto-sklearn,它通过自动考虑相似数据集上的过去性能以及构造在优化过程中评估的模型的结合来改进现有的 AutoML 方法。我们的系统在第一个 ChaLearn AutoML 挑战的十个阶段中赢得了六个,而我们对 100 多个不同数据集的综合分析表明,它的性能大大优于 AutoML 的现有技术水平。我们还将说明由于我们的每个贡献的到的提升,以及推导出的对 Auto-sklearn 各个组件有效性的见解。

简介

机器学习最近在许多应用领域取得了长足进步,推动了对机器学习系统不断增长的需求,这些系统可以被机器学习的新手高效地使用。相应地,越来越多的企业旨在满足这一需求(例如,BigML.com,Wise.io,H2O.ai,feedzai.com,RapidMiner.com,Prediction.io,DataRobot.com,Microsoft’s Azure Machine Learning,Google’s Cloud Machine Learning Engine 和 Amazon Machine Learning)。本质上,每项有效的机器学习服务都需要解决以下基本问题:确定在给定数据集上使用哪种机器学习算法,如何对其特征进行预处理,以及如何设置所有超参数。这是我们在这项工作中要解决的问题。

更具体地说,我们研究了自动化机器学习(AutoML),即在固定的计算预算内自动(无需人工输入)为新数据集生成测试集预测的问题。形式化地,此 AutoML 问题可以表述为:

定义 1 (AutoML 问题) : 对于 i=1,…,n+mi = 1, \ldots, n + mi=1,,n+m ,使 xix_ixi 表示一个特征向量,yiy_iyi 表示相应的目标值。给定训练数据集 Dtrain={(x1,y1),…,(xn,yn)}D_{train} = \{(x_1, y_1), \ldots, (x_n, y_n) \}Dtrain={(x1,y1),,(xn,yn)} 和从相同的基础数据分布获得的测试数据集 $D_{test} = {(x_{n+1}, y_{n+1}), \ldots, (x_{n+m}, y_{n+m}) } $ 的特征向量 xn+1,…,xn+mx_{n+1}, \ldots, x_{n+m}xn+1,,xn+m ,以及资源预算 bbb 和损失度量 L(⋅,⋅)\mathcal{L}(\cdot, \cdot)L(,) ,AutoML 问题是(自动)产生准确的测试集预测 $\hat{y}{n+1}, \ldots, \hat{y}{n + m} $ 。AutoML 问题的解 $\hat{y}{n+1}, \ldots, \hat{y}{n + m} $ 的损失由 $\frac{1}{m}\sum_{j=1}^{m}\mathcal{L}(\hat{y}{n+j}, y{n+j}) $ 给出。

实际上,预算 bbb 将包括计算资源,例如 CPU 和/或时间预算和内存使用情况。该问题定义反映了第一个 ChaLearn AutoML 挑战的设置[23](另请参见第 10 章,了解第一个 AutoML 挑战的描述和分析)。我们在此处介绍的 AutoML 系统在该挑战的十个阶段中赢得了六个。

在这里,我们遵循并扩展了 Auto-WEKA [42] 首次引入的 AutoML 方法。这种方法的核心是将高度参数化的机器学习框架 FFF 与贝叶斯优化[7,40]方法结合在一起,以针对给定的数据集很好的实例化 FFF

本文的贡献是基于适用于各种机器学习框架(例如上述机器学习服务提供商所使用的框架)的原理,以各种方式扩展此 AutoML 方法,从而显著提高其效率和鲁棒性。首先,在成功完成低维优化问题[21、22、38]之后,我们通过跨数据集来确定对新数据集表现良好的机器学习框架的实例,并对其进行热启动贝叶斯优化(第 6.3.1 节)。其次,我们自动构造经过贝叶斯优化考虑的模型的联合(第 6.3.2 节)。第三,我们从流行的机器学习框架 scikit-learn [36](第 6.4 节)中实现的高性能分类器和预处理器中,精心设计一个高度参数化的机器学习框架。最后,我们使用各种各样的数据集进行了广泛的经验分析,以证明最终的 Auto-sklearn 系统优于以前的最新 AutoML 方法(第 6.5 节),以表明我们的每一项贡献都可以显着改善性能(第 6.6 节),并深入了解 Auto-sklearn 中使用的各个分类器和预处理器的性能(第 6.7 节)。

本章是我们 2015 年论文的扩展版本,其中介绍了 Auto-sklearn,该论文发表在 NeurIPS 2015 的论文集[20]中。

AutoML 作为一个 CASH 问题

我们首先回顾一下 AutoML 的形式化,这是 Auto-WEKA 的 AutoML 方法使用的组合算法选择和超参数优化(CASH)问题。AutoML 中的两个重要问题是:(1) 没有一种单一的机器学习方法在所有数据集上都表现最佳; (2) 一些机器学习方法(例如,非线性 SVM)依赖于超参数优化。后一个问题已经使用贝叶斯优化[7,40]成功攻克,如今它已成为许多 AutoML 系统的核心组件。前者问题与后者纠缠在一起,因为算法的得分取决于其超参数是否正确调整。幸运的是,可以通过单个,结构化,联合优化问题有效地解决这两个问题:

定义 2 (CASH) 令 A={A(1),…,A(R)}\mathcal{A} = \{A^{(1)}, \ldots, A^{(R)}\}A={A(1),,A(R)} 为一组算法,并让每个算法 A(j)A^{(j)}A(j) 的超参数都具有域 Λ(j)\Lambda^{(j)}Λ(j) 。 此外,令 Dtrain={(x1,y1),…,(xn,yn)}D_{train} = \{(x_1, y_1), \ldots, (x_n, y_n) \}Dtrain={(x1,y1),,(xn,yn)} 为训练集,该训练集分为 K 折交叉验证集 Dvalid(1),…,Dvalid(K)D_{valid}^{(1)}, \ldots, D_{valid}^{(K)}Dvalid(1),,Dvalid(K)Dtrain(1),…,Dtrain(K)D_{train}^{(1)}, \ldots, D_{train}^{(K)}Dtrain(1),,Dtrain(K) ,使得 Dtrain(i)=Dtrain\Dvalid(i)D_{train}^{(i)} = D_{train} \backslash D_{valid}^{(i)}Dtrain(i)=Dtrain\Dvalid(i) 。 最后,令 L(Aλ(j),Dtrain(i),Dvalid(i))\mathcal{L}(A_{\lambda}^{(j)}, \mathcal{D}_{train}^{(i)}, \mathcal{D}_{valid}^{(i)})L(Aλ(j),Dtrain(i),Dvalid(i)) 表示算法 A(j)A^{(j)}A(j)Dtrain(i)D_{train}^{(i)}Dtrain(i) 上使用超参数 λ\lambdaλ 训练时在 Dvalid(i)D_{valid}^{(i)}Dvalid(i) 上得到的损失。然后,组合算法选择和超参数优化(CASH)问题将找到使该损失最小化的联合算法和超参数设置:
A∗,λ∗∈arg⁡min⁡A(j)∈A,λ∈Λ(j)1k∑i=1KL(Aλ(j),Dtrain(i),Dvalid(i)) A^*, \lambda_* \in \mathop{\arg\min}_{A^{(j)} \in \mathcal{A}, \lambda \in \Lambda^{(j)}} \frac{1}{k} \sum_{i=1}^{K} \mathcal{L}(A_{\lambda}^{(j)}, \mathcal{D}_{train}^{(i)}, \mathcal{D}_{valid}^{(i)}) A,λargminA(j)A,λΛ(j)k1i=1KL(Aλ(j),Dtrain(i),Dvalid(i))
这种 CASH 问题最初是由 Thornton 等[42]解决,在 Auto-WEKA 系统中使用机器学习框架 WEKA [25] 和基于树的贝叶斯优化方法[5,27]。简而言之,贝叶斯优化[7]生成概率模型以捕获超参数设置与其测得的性能之间的关系。然后使用此模型选择最有希望的超参数设置(权衡空间新部分的探索与已知良好区域的开发),评估超参数设置,并使用结果更新模型并进行迭代。尽管基于高斯过程模型的贝叶斯优化(例如,Snoek等[41])在具有数值超参数的低维问题中表现最佳,但基于树的模型已被证明在高维,结构化和部分离散的概率问题上更为成功[15],例如 CASH 问题,也用于 AutoML 系统 HYPEROPT-SKLEARN [30]。在基于树的贝叶斯优化方法中,Thornton等[42] 发现基于随机森林的 SMAC [27] 优于树 Parzen 估计器 TPE [5],因此我们在本文中使用 SMAC 解决 CASH 问题。除了使用随机森林[6]之外,SMAC 的主要区别在于它可以允许通过一次评估一折实现快速交叉验证,并尽早丢弃性能不佳的超参数设置。

提高 AutoML 效率和鲁棒性的新方法

现在,我们讨论对 AutoML 方法的两个改进。首先,我们包括了一个元学习步骤,以热启动贝叶斯优化程序,从而大大提高了效率。其次,我们包括了一个自动化的集成构建步骤,使我们可以使用贝叶斯优化所发现的所有分类器。

图 6.1 概况了整个 AutoML 工作流程,包括我们的两项改进。我们注意到,我们希望它们对提供较大自由度(例如,许多算法,超参数和预处理方法)的灵活的 ML 框架更有效。

找到优秀机器学习框架实例的元学习

领域专家从以前的任务中获得知识:他们学习机器学习算法的性能。元学习领域(参见第 2 章)通过推理跨数据集的学习算法的性能来模仿此策略。在这项工作中,我们应用元学习来选择给定机器学习框架的实例,这些实例在新数据集上可能会表现良好。更具体地说,对于大量数据集,我们同时收集了性能数据和一组元特征,也就是说,数据集的特征可以被有效地计算,并且有助于确定在新的数据集上使用哪种算法。

这种元学习方法是贝叶斯优化的补充,用于优化 ML 框架。元学习可以迅速建议 ML 框架的一些实例,这些实例可能会很好地执行,但是无法提供有关性能的细粒度信息。相反,对于像整个 ML 框架一样大的超参数空间,贝叶斯优化的启动速度很慢,但是可以随着时间的推移微调性能。我们通过选择基于元学习的 k 个配置来利用这种互补性,并将其结果用于贝叶斯优化的种子。这种通过元学习进行热启动优化的方法早在[21,22,38]之前就已经成功应用,但是从来没有像搜索一个成熟的 ML 框架实例空间那样复杂的优化问题。同样地,跨数据集的学习也被应用在协同贝叶斯优化方法中[4,45];尽管这些方法很有希望,但是到目前为止,它们仅限于极少数的元特征,并且还无法应付 AutoML 中面临的高维部分离散的配置空间。

更准确地说,我们的元学习方法的工作过程如下。在离线阶段,对于数据集存储库中的每个机器学习数据集(在我们的示例中为 OpenML [43] 存储库中的 140 个数据集),我们评估了一组元特征(在下面介绍),并使用贝叶斯优化来确定和存储给定的 ML 框架的实例,该 ML 框架具有针对该数据集的强大经验性能。(详细而言,我们对三分之二的数据进行了 10 折交叉验证的 SMAC [27] 24小时,并存储了所产生的 ML 框架实例,该实例在其余的三分之一上表现出最佳性能)。 然后,给定一个新的数据集 D\mathcal{D}D ,我们计算其元特征,将所有数据集按它们到 D\mathcal{D}D 元特征空间的 L1L_1L1 距离进行排序,并选择存储的 ML 框架实例以对 k=25k = 25k=25 个最近的数据集进行评估,然后再开始用它们的结果进行贝叶斯优化。

为了表征数据集,我们从文献中实现了总共 38 个元特征,包括简单的,信息理论和统计元特征[29,33],例如有关数据点数量,特征和类的统计,以及数据偏度和目标的熵。原始出版物补充材料的表 1 中列出了所有元特征[20]。值得注意的是,我们必须排除界标元特征[37](衡量简单基学习器的表现)的显着和有效类别,因为它们的计算成本过高,无法在在线评估阶段提供帮助。我们注意到,这种元学习方法从数据集存储库的可用性中汲取了力量;由于诸如 OpenML [43] 之类的最新举措,我们预计可用数据集的数量将随着时间的推移而越来越大,从而提高了元学习的重要性。

优化过程中评估模型的自动集成构建

尽管贝叶斯超参数优化可以高效地找到最佳性能的超参数设置,但当目标只是做出良好的预测时,这是一个非常浪费的过程:搜索过程中训练的所有模型都将丢失,通常包括 一些性能几乎和最好的一样的模型。我们建议存储这些模型而不是丢弃它们,并使用有效的后处理方法(可以在第二个进程中即时运行)来构建它们的集成。与使用标准超参数优化产生的点估计相比,这种自动的集成构造避免了将自己提交给单个超参数设置,因此更加健壮(并且更不容易过度拟合)。据我们所知,我们是第一个进行这种简单观察的人,它可用于改进任何贝叶斯超参数优化方法。

众所周知,集成通常优于单个模型[24、31],并且可以从模型库中创建有效的集成[9、10]。如果集成基于的模型(1)个体间的区别较大,并且(2)产生不相关的错误[6],则集成效果特别好。由于当个体模型本质上不同时,这种可能性更大,因此集成构建特别适合于组合灵活的 ML 框架的强大实例。

然而,简单地建立由贝叶斯优化发现的模型的均匀加权集成是行不通的。相反,我们发现使用保留集上所有单个模型的预测来调整这些权重至关重要。我们尝试了不同的方法来优化这些权重:堆积 (stacking) [44],无梯度数值优化和方法集成选择[10]。虽然我们发现数值优化和堆积都会对验证集过拟合并且在计算上昂贵,但集成选择是快速而强大。简而言之,集成选择(由 Caruana 等[10] 引入)是一个贪心过程,该过程从一个空集成开始,然后迭代添加模型以最小化集成的验证损失(具有统一的权重,但允许重复)。我们在所有实验中都使用了这种技术,即通过选择替换来构建大小为 50 的集成[10]。我们使用与贝叶斯优化相同的验证集来计算整体损失。

一个实用的机器学习系统

为了设计一个强大的 AutoML 系统,我们选择 scikit-learn [36] 作为我们的基础 ML 框架,scikit-learn 是最著名和使用最广泛的机器学习库之一。它提供了广泛的已建立且有效实施的 ML 算法,并且对于专家和初学者均易于使用。由于我们的 AutoML 系统与 Auto-WEKA 非常相似,但是与 HYPEROPT-SKLEARN 一样,它也是基于 scikit-learn 的,因此我们将其称为 Auto-sklearn 。

图 6.2 是 Auto-sklearn 的机器学习管道及其组件的示意图。它包括 15 种分类算法,14 种预处理方法和 4 种数据预处理方法。我们对它们中的每一个进行了参数设置,从而产生了110个超参数的空间。其中大多数是条件超参数,只有在选择了它们各自的组件后,它们才有效。我们注意到,SMAC [27] 可以自然地处理这种条件。

表 6.1 列出了 Auto-sklearn 中的所有 15 种分类算法,它们属于不同类别,例如通用线性模型( 2 种算法),支持向量机(2),判别分析(2),最近邻(1),朴素贝叶斯(3),决策树(1)和集成(4)。与 Auto-WEKA [42](另请参见第 4 章有关 Auto-WEKA 的描述)相比,我们将配置空间集中在基本分类器上,并排除了本身由一个或多个基本分类器参数化的元模型和集成。这种集合使 Auto-WEKA 的超参数数量几乎增加了五倍(至 786),而 Auto-sklearn “仅” 具有 110 个超参数。我们使用 6.3.2 节中的事后 (post-hoc) 方法构造复杂集成。与 Auto-WEKA 相比,这具有更高的数据效率:在 Auto-WEKA 中,评估具有五个组件的集成的性能需要构建和评估五个模型;相比之下,在 Auto-sklearn 中,集成基本上是免费的,并且可以在优化过程中混合和匹配在任意时间评估的模型。

表 6.1 中列出了 Auto-sklearn 中密集表示数据集的预处理方法。它们包括数据预处理器(更改特征值并在应用时始终使用)和特征预处理器(更改实际的特征集,并且仅使用其中一个(或不使用))。数据预处理包括输入的重新缩放,缺失值的插补,one-hot 编码和目标类的平衡。这 14 种可能的特征预处理方法可以分为特征选择(2),核近似(2),矩阵分解(3),嵌入(1),特征聚类(1),多项式特征展开(1)和使用分类器进行特征选择的方法(2)。例如,通过消除与零值模型系数相对应的特征,可以将拟合数据的 L1L_1L1 正则化线性 SVM 用于特征选择。

有关 Auto-sklearn 中使用的机器学习算法的详细说明,请参阅 A.1 节和 A.2 节,它们是原始论文的补充材料,scikit-learn 学习文档[36]以及其中的参考文献。

为了充分利用我们的算力,并且避免陷入预处理和机器学习算法某种组合的缓慢运行中,我们采取了几种措施来防止这种长期运行。首先,我们限制了每次评估 ML 框架实例的时间。我们还限制了此类评估的内存,以防止操作系统交换或冻结。当评估超过这些限制时,我们会自动终止该评估,并返回给定评估指标的最差得分。对于某些模型,我们采用了迭代训练程序;当它们在终止之前达到限制时,我们指示它们仍然返回其当前性能值。为了进一步减少过长的运行,我们禁止预处理器和分类方法的几种组合:特别是,禁止将非线性和基于树的方法以及 KNN 算法结合使用内核近似。( SMAC 自然地处理此类禁止的组合)出于同样的原因,我们还省略了特征学习算法,例如字典学习。

超参数优化的另一个问题是过拟合和数据重采样,因为必须将 AutoML 系统的训练数据分为用于训练 ML 管道的数据集(训练集)和用于计算贝叶斯优化的损失函数的数据集(验证集)。在这里,我们必须在运行更强大的交叉验证(这在 SMAC 中几乎没有额外的开销)与在所有交叉验证折上评估模型模型之间进行权衡,以允许使用这些模型进行合理的构建。因此,对于第 6.6 节中的严格时间限制为 1 小时的任务,我们采用了简单的训练/测试拆分。相比之下,我们在第 6.5 和 6.7 节的 24 小时和 30 小时运行中可以采用十折交叉验证。

最后,并非所有监督学习任务(例如,具有多个目标的分类)都可以通过 Auto-sklearn 中所有可用的算法来解决。因此,在给定新数据集的情况下,Auto-sklearn 会预先选择适合数据集属性的方法。由于 scikit-learn 方法仅限于数字输入值,因此我们始终通过对分类特征应用 one-hot 编码来转换数据。为了使虚拟特征的数量保持在较低水平,我们配置了百分比阈值,并且将比该百分比更低的值转换为特殊的其他值[35]。

将 Auto-sklearn 与 Auto-WEKA 和 HYPEROPT-SKLEARN 对比

作为基线实验,我们将基本 Auto-sklearn(没有改进的元学习和集成构建)与 Auto-WEKA(请参见第 4 章)和 Hyperopt-Sklearn(请参见第 5 章)的性能进行了比较,按照 Auto-WEKA [42] 的论文的 21 个数据集(有关数据集的描述,请参见第 4 章中的表 4.1 )重现了实验设置。按照 Auto-WEKA 论文的原始设置,我们对数据集使用了相同的训练/测试拆分[1],时间限制为 30 小时,10 折交叉验证(其中对每一折的评估时间为 150 分钟) ,并且在每个数据集上使用 SMAC 进行 10 次独立优化。与 Auto-WEKA 中一样,评估由 SMAC 的强化程序加速,如果当前正在评估的配置可能胜过迄今为止表现最好的配置,则仅在新的交叉验证折上运行计划配置[27]。我们并未修改 HYPEROPT-SKLEARN ,它始终使用 80/20 训练/测试划分。我们所有的实验均在具有 2.60 GHz 和 4 GiB RAM 的 Intel Xeon E5-2650 v2 八核处理器上运行。我们允许机器学习框架使用 3 GiB 内存,其余的留给 SMAC 。所有实验均使用 Auto-WEKA 0.5 和 scikit-learn 0.16.1 。

我们在表 6.2 中展示了该实验的结果。由于我们的设置与原始 Auto-WEKA 论文完全相同,因此,为了进行完整的检测,我们将自己获得的 Auto-WEKA 结果(图 6.2 中的第一行)与 Auto-WEKA 的作者提供的结果(请参见第 4 章)进行了比较。并发现总体结果是合理的。此外,该表还显示,在 6/21 案例中,Auto-sklearn 的性能显着优于 Auto-WEKA,在 12 个案例中并列,而在 3 个案例中较差。对于 Auto-WEKA 表现最佳的三个数据集,我们发现其中的 50% 选择的最佳分类器未在 scikit-learn 中实现(带有剪枝组件的树)。到目前为止,与完整的 AutoML 系统相比,HYPEROPT-SKLEAR 还提供了概念验证(邀请用户根据自己的需要调整配置空间)。当出现稀疏数据和缺失值时,当前版本会崩溃。由于我们为所有优化程序设置内存限制,以实现公平的比较,因此它在 Cifar-10 上也会崩溃。在运行的 16 个数据集上,它在 9 个案例的统计上与最具竞争力的 AutoML 系统并列,而在 7 个案例中输给了它。

评估提出的 AutoML 改进

为了评估我们提出的 AutoML 系统在各种数据集上的鲁棒性和普遍适用性,我们从 OpenML 存储库中收集了 140 个二元和多类分类数据集[43],仅选择至少具有 1000 个数据点的数据集以进行鲁棒的性能评估。涵盖了多种应用,例如文本分类,数字和字母识别,基因序列和 RNA 分类,推荐,望远镜数据的粒子分类以及组织样本中的癌症检测。我们在补充资料中列出了表 7 和 8 中的所有数据集原始出处[20]的材料并提供其独特的 OpenML ID 以确保可重复性。我们将每个数据集随机分为三分之二的训练集和三分之一的测试集。Auto-sklearn 仅可访问训练集,并将其进一步分为两部分,三分之二用于训练,三分之一作为保留集用于计算 SMAC 的验证损失。总而言之,我们使用了 4/9 的数据来训练机器学习模型,使用了2/9 的数据来计算其验证损失,最后 3/9 的数据来报告所比较的不同 AutoML 系统的测试性能。由于许多此类数据集中的类分布非常不平衡,因此我们使用一种称为平衡分类错误率(BER)的评估方法来评估所有 AutoML 方法。我们将平衡错误率定义为每个类别中错误分类所占比例的平均值。与标准分类错误(平均总体错误)相比,此度量(按类错误的平均值)为所有类别分配了相等的权重。我们注意到在机器学习竞赛中经常使用平衡的误差或准确性测度,例如在第 10 章中描述的 AutoML 挑战[23]。

我们在每个数据集上分别进行了 10 次包含基不包含元学习和集成构件的 Auto-sklearn 的运行。为了研究在严格的时间限制下,和计算资源的限制下,而产生的性能,我们将每次运行的 CPU 时间限制为 1 小时。我们还将用于评估单个模型的运行时间限制为该时间的十分之一(6分钟)。

为了不评估已经用于元学习的数据集的性能,我们执行了留一数据集验证:当对数据集 D\mathcal{D}D 进行评估时,仅使用来自其他 139 个数据集的元信息。

图 6.3 显示了我们测试的四个 Auto-sklearn 版本随时间的平均排名。我们观察到,我们的两种新方法都比基础 Auto-sklearn 有了实质性的改进。 最引人注目的结果是,元学习从其选择的第一个配置开始一直持续到实验结束为止,都取得了巨大的进步。我们注意到,这种改进在开始时最为明显,随着时间的流逝,基础 Auto-sklearn 也找到了无需元学习的良好解决方案,从而使它可以在某些数据集取得好的结果(从而提高了整体排名)。

此外,我们的两种方法相得益彰:我们的自动集成构建改进了基础 Auto-sklearn 和带元学习的 Auto-sklearn 。有趣的是,集成对性能的影响是在元学习版本体现的更早。我们认为这是因为元学习可以更早地产生更好的机器学习模型,并且可以直接组在一个强大的集成中;但是,当运行时间更长时,无需进行元学习的基础自动 Auto-sklearn 也可以从自动集成构建中受益。

Auto-sklearn 组件的详细分析

现在,我们将研究 Auto-sklearn 的各个分类器和预处理器,与共同优化所有方法比较,以便深入了解它们的最佳性能和鲁棒性。理想情况下,我们本来希望单独研究单个分类器和单个预处理器的所有组合,但是使用 15 个分类器和 14 个预处理器是不可行的;因此,在研究单个分类器的性能时,我们仍然对所有预处理器进行了优化,反之亦然。为了获得更详细的分析,我们将重点放在数据集的子集上,但是将为 Auto-sklearn 优化所有方法配置的预算从 1 消失扩展为一天和两天。具体来说,我们基于数据集的元特征将计算出 g 均值 (g-mean) [26] 的 140 个数据集进行了聚类,并从结果的 13 个聚类中每个聚类使用了一个数据集。我们在表 6.3 中给出了数据集的基本描述。总的来说,这些广泛的实验需要 10.7 CPU 年。

表 6.4 比较了针对 Auto-sklearn 的各种分类方法的结果。总体而言,正如预期的那样,随机森林,极度随机的树,AdaBoost 和梯度增强显示出最具鲁棒性的性能,而 SVM 对某些数据集显示出强大的峰值性能。除了各种强分类器外,还有几种模型无法与之抗衡:决策树,被动侵略,kNN,高斯 NB,LDA 和 QDA 在大多数数据集的统计上显著低于最佳分类器。最后,该表表明没有一种方法是所有数据集的最佳选择。如表中所示,并在图 6.4 中可视化了两个示例数据集,优化 Auto-sklearn 的联合配置空间可实现鲁棒性最好的性能。随时间推移的排名(原出处[20]的补充材料中的图 2 和图 3)对所有13个数据集进行了量化,表明 Auto-sklearn 以合理但并非最佳的性能开始,并有效地搜索其更一般的配置空间以随时间推移收敛到获得最佳整体性能。

表 6.5 对比了各种预处理器与 Auto-sklearn 的结果。至于上面分类器的比较,Auto-sklearn 表现出最强大的性能:它在三个数据集上表现最佳,并且在另外 8/13 从统计上说也没有比最佳预处理器差。

讨论和结论

介绍了我们的实验验证之后,我们现在通过简短的讨论结束本章,简要介绍 Auto-sklearn 的用法示例,简要回顾一下最新的扩展,并总结一下。

讨论

我们证明了我们新的 AutoML 系统 Auto-sklearn 相对于 AutoML 的现有技术表现出色,并且我们 AutoML 的元学习和集成改进产生了更高的效率和鲁棒性。这一发现得到了以下事实的支持:Auto-sklearn 在 ChaLearn 的第一个 AutoML 挑战中赢得了五条自动化赛道中的三条,其中包括最后两条。在本文中,我们没有评估 Auto-sklearn 在交互式机器学习中与专家一起在几周的 CPU 算力上的使用,但我们注意到,该模式已产生第一个 ChaLearn AutoML 竞赛中(自动化赛道之外,尤其是表 10.5,阶段 Final 0-4)的人类(也称为 Final)赛道中的三个首位。 因此,我们认为 Auto-sklearn 是机器学习新手和专家都可以使用的有前途的系统。

自从初始的 NeurIPS 论文[20]发表以来,Auto-sklearn 已成为自动化机器学习新方法的标准基准,例如 FLASH [46],RECIPE [39],Hyperband [32],AutoPrognosis [3],ML -PLAN [34],Auto-Stacker[11] 和 AlphaD3M [13]。

使用

Auto-sklearn Python 包是 Auto-sklearn 研究的重要成果之一。它是任何 scikit-learn 分类器或回归器的直接替代,类似于 HYPEROPT-SKLEARN [30] 提供的分类器,可按以下方式使用:

Auto-sklearn 可以与任何损失函数和重采样策略一起使用,以估计验证损失。此外,可以扩展 Auto-sklearn 可选择的分类器和预处理器。自最初发布以来,我们还为 Auto-sklearn 添加了回归支持。我们在 https://github.com/automl/auto-sklearn 上开发了该程序包,可通过 Python Packaging index pypi.org 获得该程序包。我们在 automl.github.io/auto-sklearn 上提供了文档。

PoSH Auto-sklearn 的扩展

虽然本章所述的 Auto-sklearn 仅限于处理大小相对较小的数据集,但在最近的 AutoML 挑战(AutoML 2,于 2018 年运行;请参见第10章)的背景下,我们将其扩展为也可以有效地处理大型数据集。Auto-sklearn 通过使用 25 个 CPU 的集群进行了两天的处理,可以处理成百上千个数据点的数据集,但不符合 AutoML 2 挑战要求的 20 分钟时间预算。正如在最新的研讨会论文[18]中详细描述的那样,这意味着要开放对于包括以下方法的考虑,极端梯度提升 (尤其是 XGBoost) ,使用连续减半的多保真方法[28] (也在第 1 章中介绍) 来解决 CASH 问题,并修改我们的元学习方法。现在,我们简要描述所产生的系统 PoSH Auto-sklearn ( Portfolio Successive Halfving 的缩写,再与 Auto-sklearn 组合),该系统在 2018 年的挑战中获得了最佳性能。

PoSH Auto-sklearn 首先使用固定的 16 种机器学习管道配置组合进行连续减半,然后,如果还有时间,它将利用这些运行的结果来热启动贝叶斯优化和连续减半的组合。通过运行贪婪的次模函数最大化来选择一组强大的互补配置,以优化在 421 个数据集上获得的性能,从而得到 16 条管道的固定组合;为此优化配置的候选配置是通过在这 421 个数据集中的每个数据集上运行 SMAC [27] 而找到的 421 个配置。

贝叶斯优化和我们为了在短时间窗内获得稳健结果而使用的连续减半的组合是对第 1 章中讨论的多保真超参数优化方法 BOHB(贝叶斯优化和 HyperBand )[17]的修改。我们使用了所有迭代算法的迭代次数作为这种多保真方法的预算,但 SVM 除外,在 SVM 中,我们使用数据集大小作为预算。

当前正在针对大型数据集进行的另一项扩展是我们在自动化深度学习方面的工作。这将在下一章 Auto-Net 中进行讨论。

结论和未来工作

继 Auto-WEKA 采用 AutoML 方法之后,我们引入了 Auto-sklearn,它比 AutoML 的现有技术方面表现更加出色,并且还证明了我们的元学习和集成机制可进一步提高其效率和鲁棒性。

当 Auto-sklearn 为用户处理超参数调整时,Auto-sklearn 自身具有超参数,这些参数会影响给定时间预算的性能,例如第 6.5、6.6 和 6.7 节中讨论的时间限制,或者用于计算损失函数的重采样策略。我们在前期工作中证明,重采样策略的选择和超时时间的选择本身可以作为元学习问题来解决[19],但我们希望将其扩展到 Auto-sklearn 用户面临的其他可能的设计选择中。

自从撰写原始论文以来,元学习领域取得了长足的进步,使人们可以使用多种新方法将元信息包含在贝叶斯优化中。我们期望使用在第 2 章中讨论的较新的方法可以大大改善优化程序。

最后,拥有可以测试数百个超参数配置的全自动程序,使我们面临对验证集过拟合的风险,为了避免这种过拟合,我们希望将 Auto-sklearn 与第 1 章中讨论的技术结合使用,来自差异隐私 (differential privacy) [14]的技术或其他尚未开发的技术。

from autosklearn.regression import AutoSklearnRegressor from autosklearn.classification import AutoSklearnClassifier from sklearn.cluster import KMeans, SpectralClustering, AgglomerativeClustering from sklearn.feature_selection import RFECV from sklearn.metrics import silhouette_score, calinski_harabasz_score, davies_bouldin_score import numpy as np import pandas as pd import time from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, f1_score, accuracy_score, precision_score, recall_score, r2_score, mean_absolute_error, mean_squared_error from sklearn.preprocessing import StandardScaler from sklearn.model_selection import cross_val_score from sklearn.linear_model import LogisticRegression from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor from sklearn.ensemble import RandomForestClassifier, ExtraTreesClassifier, AdaBoostClassifier, GradientBoostingClassifier, RandomForestRegressor, ExtraTreesRegressor, GradientBoostingRegressor from xgboost import XGBClassifier, XGBRegressor from sklearn.svm import SVC from lightgbm import LGBMClassifier, LGBMRegressor from bayes_opt import BayesianOptimization from sklearn.utils import resample df_fire = pd.read_csv("gds_fire_30mm.csv") df_nofire = pd.read_csv("gds_nofire_30mm.csv") df = pd.concat([df_fire,df_nofire]) features = ['system:index', 'days', 'evisum', 'ndwisum', 'ndvisum', 'lstsum', '.geo', 'time'] df = df.drop(features, axis = 1) df = df[df.apply(lambda row: row.isin([-99999.000000]).sum() == 0, axis=1)] # 加载数据集并进行标准化处理 X = df.drop(['labels'], axis = 1).values y = df['labels'].values scaler = StandardScaler() X_scaled = scaler.fit_transform(X) X_resampled, y_resampled = resample(X_scaled, y, replace=True, n_samples=len(y==1), random_state=42) X_train_resampled, X_test_resampled, y_train_resampled, y_test_resampled = train_test_split(X_resampled, y_resampled, test_size=0.3, random_state=42) automl = AutoSklearnClassifier( time_left_for_this_task=120*5, per_run_time_limit=30, metric=autosklearn.metrics.accuracy, seed=42, resampling_strategy='cv', resampling_strategy_arguments={'folds': 5} ) automl.fit(X_train_resampled, y_train_resampled) automl.leaderboard(detailed = True, ensemble_only=False) print(automl.sprint_statistics()) 报错:[ERROR] [2025-08-01 03:56:04,284:Client-AutoML(42):7119140d-6e8b-11f0-9494-024264400002] (' Dummy prediction failed with run state StatusType.CRASHED and additional output: {\'error\': \'Result queue is empty\', \'exit_status\': "<class \'pynisher.limit_function_call.AnythingException\'>", \'subprocess_stdout\': \'\', \'subprocess_stderr\': \'Process pynisher function call:\\nTraceback (most recent call last):\\n File "/opt/conda/envs/mmedu/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap\\n self.run()\\n File "/opt/conda/envs/mmedu/lib/python3.8/multiprocessing/process.py", line 108, in run\\n self._target(*self._args, **self._kwargs)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/pynisher/limit_function_call.py", line 133, in subprocess_func\\n return_value = ((func(*args, **kwargs), 0))\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/__init__.py", line 55, in fit_predict_try_except_decorator\\n return ta(queue=queue, **kwargs)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/train_evaluator.py", line 1386, in eval_cv\\n evaluator = TrainEvaluator(\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/train_evaluator.py", line 206, in __init__\\n super().__init__(\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/abstract_evaluator.py", line 215, in __init__\\n threadpool_limits(limits=1)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 794, in __init__\\n super().__init__(ThreadpoolController(), limits=limits, user_api=user_api)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 587, in __init__\\n self._set_threadpool_limits()\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 720, in _set_threadpool_limits\\n lib_controller.set_num_threads(num_threads)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 199, in set_num_threads\\n return set_num_threads_func(num_threads)\\nKeyboardInterrupt\\n\', \'exitcode\': 1, \'configuration_origin\': \'DUMMY\'}.',) [ERROR] [2025-08-01 03:56:04,284:Client-AutoML(42):7119140d-6e8b-11f0-9494-024264400002] (' Dummy prediction failed with run state StatusType.CRASHED and additional output: {\'error\': \'Result queue is empty\', \'exit_status\': "<class \'pynisher.limit_function_call.AnythingException\'>", \'subprocess_stdout\': \'\', \'subprocess_stderr\': \'Process pynisher function call:\\nTraceback (most recent call last):\\n File "/opt/conda/envs/mmedu/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap\\n self.run()\\n File "/opt/conda/envs/mmedu/lib/python3.8/multiprocessing/process.py", line 108, in run\\n self._target(*self._args, **self._kwargs)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/pynisher/limit_function_call.py", line 133, in subprocess_func\\n return_value = ((func(*args, **kwargs), 0))\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/__init__.py", line 55, in fit_predict_try_except_decorator\\n return ta(queue=queue, **kwargs)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/train_evaluator.py", line 1386, in eval_cv\\n evaluator = TrainEvaluator(\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/train_evaluator.py", line 206, in __init__\\n super().__init__(\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/abstract_evaluator.py", line 215, in __init__\\n threadpool_limits(limits=1)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 794, in __init__\\n super().__init__(ThreadpoolController(), limits=limits, user_api=user_api)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 587, in __init__\\n self._set_threadpool_limits()\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 720, in _set_threadpool_limits\\n lib_controller.set_num_threads(num_threads)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 199, in set_num_threads\\n return set_num_threads_func(num_threads)\\nKeyboardInterrupt\\n\', \'exitcode\': 1, \'configuration_origin\': \'DUMMY\'}.',) Traceback (most recent call last): File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/automl.py", line 765, in fit self._do_dummy_prediction() File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/automl.py", line 489, in _do_dummy_prediction raise ValueError(msg) ValueError: (' Dummy prediction failed with run state StatusType.CRASHED and additional output: {\'error\': \'Result queue is empty\', \'exit_status\': "<class \'pynisher.limit_function_call.AnythingException\'>", \'subprocess_stdout\': \'\', \'subprocess_stderr\': \'Process pynisher function call:\\nTraceback (most recent call last):\\n File "/opt/conda/envs/mmedu/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap\\n self.run()\\n File "/opt/conda/envs/mmedu/lib/python3.8/multiprocessing/process.py", line 108, in run\\n self._target(*self._args, **self._kwargs)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/pynisher/limit_function_call.py", line 133, in subprocess_func\\n return_value = ((func(*args, **kwargs), 0))\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/__init__.py", line 55, in fit_predict_try_except_decorator\\n return ta(queue=queue, **kwargs)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/train_evaluator.py", line 1386, in eval_cv\\n evaluator = TrainEvaluator(\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/train_evaluator.py", line 206, in __init__\\n super().__init__(\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/abstract_evaluator.py", line 215, in __init__\\n threadpool_limits(limits=1)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 794, in __init__\\n super().__init__(ThreadpoolController(), limits=limits, user_api=user_api)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 587, in __init__\\n self._set_threadpool_limits()\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 720, in _set_threadpool_limits\\n lib_controller.set_num_threads(num_threads)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 199, in set_num_threads\\n return set_num_threads_func(num_threads)\\nKeyboardInterrupt\\n\', \'exitcode\': 1, \'configuration_origin\': \'DUMMY\'}.',) --------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[15], line 9 1 automl = AutoSklearnClassifier( 2 time_left_for_this_task=120*5, 3 per_run_time_limit=30, (...) 7 resampling_strategy_arguments={'folds': 5} 8 ) ----> 9 automl.fit(X_train_resampled, y_train_resampled) 10 automl.leaderboard(detailed = True, ensemble_only=False) 11 print(automl.sprint_statistics()) File /opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/estimators.py:1448, in AutoSklearnClassifier.fit(self, X, y, X_test, y_test, feat_type, dataset_name) 1445 # remember target type for using in predict_proba later. 1446 self.target_type = target_type -> 1448 super().fit( 1449 X=X, 1450 y=y, 1451 X_test=X_test, 1452 y_test=y_test, 1453 feat_type=feat_type, 1454 dataset_name=dataset_name, 1455 ) 1457 # After fit, a classifier is expected to define classes_ 1458 # A list of class labels known to the classifier, mapping each label 1459 # to a numerical index used in the model representation our output. 1460 self.classes_ = self.automl_.InputValidator.target_validator.classes_ File /opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/estimators.py:540, in AutoSklearnEstimator.fit(self, **kwargs) 538 if self.automl_ is None: 539 self.automl_ = self.build_automl() --> 540 self.automl_.fit(load_models=self.load_models, **kwargs) 542 return self File /opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/automl.py:2304, in AutoMLClassifier.fit(self, X, y, X_test, y_test, feat_type, dataset_name, only_return_configuration_space, load_models) 2293 def fit( 2294 self, 2295 X: SUPPORTED_FEAT_TYPES, (...) 2302 load_models: bool = True, 2303 ) -> AutoMLClassifier: -> 2304 return super().fit( 2305 X, 2306 y, 2307 X_test=X_test, 2308 y_test=y_test, 2309 feat_type=feat_type, 2310 dataset_name=dataset_name, 2311 only_return_configuration_space=only_return_configuration_space, 2312 load_models=load_models, 2313 is_classification=True, 2314 ) File /opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/automl.py:962, in AutoML.fit(self, X, y, task, X_test, y_test, feat_type, dataset_name, only_return_configuration_space, load_models, is_classification) 959 except Exception as e: 960 # This will be called before the _fit_cleanup 961 self._logger.exception(e) --> 962 raise e 963 finally: 964 self._fit_cleanup() File /opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/automl.py:765, in AutoML.fit(self, X, y, task, X_test, y_test, feat_type, dataset_name, only_return_configuration_space, load_models, is_classification) 763 with self._stopwatch.time("Dummy predictions"): 764 self.num_run += 1 --> 765 self._do_dummy_prediction() 767 # == RUN ensemble builder 768 # Do this before calculating the meta-features to make sure that the 769 # dummy predictions are actually included in the ensemble even if 770 # calculating the meta-features takes very long 771 with self._stopwatch.time("Run Ensemble Builder"): File /opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/automl.py:489, in AutoML._do_dummy_prediction(self) 483 msg = ( 484 f" Dummy prediction failed with run state {status} and" 485 f" additional output: {additional_info}.", 486 ) 488 self._logger.error(msg) --> 489 raise ValueError(msg) 491 return ValueError: (' Dummy prediction failed with run state StatusType.CRASHED and additional output: {\'error\': \'Result queue is empty\', \'exit_status\': "<class \'pynisher.limit_function_call.AnythingException\'>", \'subprocess_stdout\': \'\', \'subprocess_stderr\': \'Process pynisher function call:\\nTraceback (most recent call last):\\n File "/opt/conda/envs/mmedu/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap\\n self.run()\\n File "/opt/conda/envs/mmedu/lib/python3.8/multiprocessing/process.py", line 108, in run\\n self._target(*self._args, **self._kwargs)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/pynisher/limit_function_call.py", line 133, in subprocess_func\\n return_value = ((func(*args, **kwargs), 0))\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/__init__.py", line 55, in fit_predict_try_except_decorator\\n return ta(queue=queue, **kwargs)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/train_evaluator.py", line 1386, in eval_cv\\n evaluator = TrainEvaluator(\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/train_evaluator.py", line 206, in __init__\\n super().__init__(\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/autosklearn/evaluation/abstract_evaluator.py", line 215, in __init__\\n threadpool_limits(limits=1)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 794, in __init__\\n super().__init__(ThreadpoolController(), limits=limits, user_api=user_api)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 587, in __init__\\n self._set_threadpool_limits()\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 720, in _set_threadpool_limits\\n lib_controller.set_num_threads(num_threads)\\n File "/opt/conda/envs/mmedu/lib/python3.8/site-packages/threadpoolctl.py", line 199, in set_num_threads\\n return set_num_threads_func(num_threads)\\nKeyboardInterrupt\\n\', \'exitcode\': 1, \'configuration_origin\': \'DUMMY\'}.',)
08-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值