7x24快讯 ·

Python 环境下的自动化机器学习超参数调优

机器学习算法的性能高度依赖于超参数的选择,对机器学习超参数进行调优是一项繁琐但却至关重要的任务。本文介绍了一个使用「Hyperopt」库对梯度提升机(GBM)进行贝叶斯超参数调优的完整示例,并着重介绍了其实现过程。

由于机器学习算法的性能高度依赖于超参数的选择,对机器学习超参数进行调优是一项繁琐但至关重要的任务。手动调优占用了机器学习算法流程中一些关键步骤(如特征工程和结果解释)的时间。网格搜索和随机搜索则不会干涉这些步骤,但是需要大量的运行时间,因为它们浪费了时间去评估搜索空间中并不太可能找到最优点的区域。如今越来越多的超参数调优过程都是通过自动化的方法完成的,它们旨在使用带有策略的启发式搜索(informed search)在更短的时间内找到最优超参数,除了初始设置之外,并不需要额外的手动操作。

贝叶斯优化是一种基于模型的用于寻找函数最小值的方法。近段时间以来,贝叶斯优化开始被用于机器学习超参数调优,结果表明,该方法在测试集上的表现更加优异,但需要的迭代次数小于随机搜索。此外,现在一些 Python 库的出现使得对任意的机器学习模型实现贝叶斯超参数调优变得更加简单。

本文将介绍一个使用「Hyperopt」库对梯度提升机(GBM)进行贝叶斯超参数调优的完整示例。在本文作者早先的一篇文章中,他已经对这个方法背后的概念进行了概述,所以本文将着重介绍实现过程。和大多数机器学习的主题类似,读者并不需要理解所有的细节,但是了解基本的原理可以帮助读者更有效地使用这项技术!

本文所有的代码都可以以 Jupyter Notebook 的形式在 GitHub 上获取(https://github.com/WillKoehrsen/hyperparameter-optimization)。

本文目录:

贝叶斯优化方法
优化问题的四个组成部分
目标函数
域空间
优化算法
结果的历史数据
优化
搜索结果
搜索结果的可视化
搜索的演化过程
继续搜索
结语

贝叶斯优化方法

简单地说,贝叶斯优化通过基于过去对目标的评估结果建立一个代理函数(概率模型)找到使得目标函数最小的值。代理函数比目标函数更易于优化,因此下一个待评估的输入值是通过对代理函数应用某种标准(通常为预期提升)来选择的。贝叶斯方法不同于随机搜索或网格搜索,后两者都使用了过去的评估结果来选择接下来待评估的值。它们的思想是:通过根据过去表现良好的值选择下一个输入值来限制评价目标函数的高昂开销。

对于超参数优化来说,其目标函数为使用一组超参数的机器学习模型的验证误差。它的目标是找出在验证集上产生最小误差的超参数,并希望将这些结果泛化到测试集上去。对目标函数评估的开销是巨大的,因为它需要训练带有一组特定超参数的机器学习模型。理想情况下,我们希望找到这样一方法,它既能探索搜索空间,又能限制耗时的超参数评估。贝叶斯超参数调优使用一个不断更新的概率模型,通过从过去的结果中进行推理,使搜索过程「专注」于有可能达到最优的超参数。

Python 环境下有一些贝叶斯优化程序库,它们目标函数的代理算法有所区别。在本文中,我们将使用「Hyperopt」库,它使用树形 Parzen 评估器(TPE,https://papers.nips.cc/paper/4443-algorithms-for-hyper-parameter-optimization.pdf)作为搜索算法,其他的 Python 库还包含「Spearmint」(高斯过程代理)和「SMAC」(随即森林回归)。目前在这个领域有大量有趣的研究,所以如果你对某一个库不是很满意,你可以试试其他的选项!针对某个问题的通用结构(本文将使用的结构)可以在各个库间进行转换,其句法差异非常小。

优化问题的四个组成部分

贝叶斯优化问题有四个组成部分:

1. 目标函数:我们想要最小化的对象,这里指带超参数的机器学习模型的验证误差

2. 域空间:待搜索的超参数值

3. 优化算法:构造代理模型和选择接下来要评估的超参数值的方法

4. 结果的历史数据:存储下来的目标函数评估结果,包含超参数和验证损失

通过以上四个步骤,我们可以对任意实值函数进行优化(找到最小值)。这是一个强大的抽象过程,除了机器学习超参数的调优,它还能帮我们解决其他许多问题。

数据集

在本文的示例中,我们将使用 Caravan Insurance 数据集(https://www.kaggle.com/uciml/caravan-insurance-challenge),它的目标是预测客户是否会购买一份保险产品。这是一个监督分类问题,带有 5800 个用于训练的观测值和 4000 个测试点。由于这是一个不平衡的分类问题,本文使用的评价性能的指标是受试者工作特征曲线下的面积(ROC AUC),ROC AUC 的值越高越好,其值为 1 代表模型是完美的。数据集如下所示:

?

?

数据集(CARAVAN)是带标签的

由于 Hyperopt 要做的是取最小值,我们将从目标函数中返回「1-ROC AUC」,从而提高 ROC AUC。

梯度提升模型

在本文中,我们对梯度提升机(GBM)的细节知识不做过多探讨,下面是我们需要理解的基本知识:GBM 是一种基于使用依次训练的弱学习器(多为决策树)构建强学习器的集成增强方法。GBM 中有许多超参数,它们控制着整个集成结构和单棵决策树。我们在这里使用的一种最有效的选择决策树数量的方法(称为评估器)是早停止(early stopping)。LightGBM 提供了一种 Python 环境下的快速简单的 GBM 实现。

想了解更多 GBM 的细节,这里有一篇高屋建瓴的文章:https://medium.com/mlreview/gradient-boosting-from-scratch-1e317ae4587d

一篇技术论文:https://brage.bibsys.no/xmlui/bitstream/handle/11250/2433761/16128_FULLTEXT.pdf

抛开必要的背景知识不谈,让我们将用于超参数调优的贝叶斯优化问题的四个组成部分一一列举出来。

目标函数

我们试图最小化目标函数。其输入为一组值——在本例中为 GBM 的超参数,输出为需要最小化的实值——交叉验证损失。Hyperopt 将目标函数作为黑盒处理,因为这个库只关心输入和输出是什么。为了找到使损失最小的输入值,该算法不需要知道目标函数的内部细节!从一个高度抽象的层次上说(以伪代码的形式),我们的目标函数可以表示为:

?

?

在对最终的模型进行评价时,我们需要注意的是,不要使用测试集上的损失,因为我们只能使用一次测试集。相对地,我们对验证集上的超参数进行评估。此外,我们使用 K 折交叉验证而不是将数据划分到一个独立的验证集中,这种验证方法除了保留了有价值的训练数据外,还能让我们在测试集上获得偏差更小的误差估计。

不同模型超参数调优的目标函数的基本结构是相同的:函数接收超参数作为输入,并返回使用这些超参数的交叉验证误差。尽管本文的示例是针对 GBM 的,但该结构同样可以被应用于其他的方法。

下图为 GBM 的完整目标函数,该 GBM 使用带早停止机制的 10 折交叉验证:

?

参与评论