Scikit-Optimize 用于机器学习中的超参数调优

超参数优化是指通过搜索来发现一组特定的模型配置参数,这些参数能够使模型在特定数据集上达到最佳性能。

执行超参数优化有许多方法,尽管现代方法,如贝叶斯优化,既快速又有效。**Scikit-Optimize 库**是一个开源的 Python 库,它提供了贝叶斯优化的实现,可用于调整 scikit-Learn Python 库中机器学习模型的超参数。

您可以在下一个机器学习项目中使用 Scikit-Optimize 库轻松地调整模型。

在本教程中,您将学习如何使用 Scikit-Optimize 库使用贝叶斯优化进行超参数调优。

完成本教程后,您将了解:

  • Scikit-Optimize 提供了一个通用的贝叶斯优化工具包,可用于超参数调优。
  • 如何手动使用 Scikit-Optimize 库来调整机器学习模型的超参数。
  • 如何使用内置的 BayesSearchCV 类执行模型超参数调优。

让我们开始吧。

  • 更新 2020年11月:由于 skopt 网站发生更改,已更新损坏的 API 链接。
Scikit-Optimize for Hyperparameter Tuning in Machine Learning

Scikit-Optimize 用于机器学习中的超参数调优
照片由 Dan Nevill 拍摄,部分权利保留。

教程概述

本教程分为四个部分;它们是

  1. Scikit-Optimize
  2. 机器学习数据集和模型
  3. 手动调优算法超参数
  4. 自动调优算法超参数

Scikit-Optimize

Scikit-Optimize,简称 skopt,是一个用于执行优化任务的开源 Python 库。

它提供了高效的优化算法,例如贝叶斯优化,并可用于寻找任意成本函数的最小值或最大值。

贝叶斯优化提供了一种基于贝叶斯定理的有原则的技术,用于指导全局优化问题的搜索,该搜索既高效又有效。它通过构建目标函数的概率模型(称为代理函数),然后使用采集函数对其进行高效搜索,最后选择候选样本在实际目标函数上进行评估。

有关贝叶斯优化的更多信息,请参阅教程

重要的是,该库支持调整 scikit-learn 库提供的机器学习算法的超参数,即所谓的超参数优化。因此,它提供了一种比网格搜索和随机搜索等效率较低的超参数优化过程更有效的方法。

可以使用 pip 安装 scikit-optimize 库,如下所示:

安装完成后,我们可以导入该库并打印版本号,以确认库已成功安装并可以访问。

完整的示例如下所示。

运行示例将报告 scikit-optimize 的当前安装版本号。

您的版本号应与此相同或更高。

有关更多安装说明,请参阅文档

现在我们已经了解了 Scikit-Optimize 是什么以及如何安装它,让我们探讨一下如何使用它来调整机器学习模型的超参数。

机器学习数据集和模型

首先,让我们选择一个标准数据集和一个模型来处理它。

我们将使用电离层机器学习数据集。这是一个标准机器学习数据集,包含 351 行数据,具有三个数值输入变量和一个具有两个类值的目标变量,例如二元分类。

使用重复分层 10 折交叉验证和三次重复的测试框架,朴素模型可以达到约 64% 的准确率。表现最佳的模型在此测试框架上可达到约 94% 的准确率。这为该数据集上的预期性能提供了界限。

该数据集涉及预测电离层测量是否指示特定结构。

你可以在此处了解更多关于此数据集的信息:

无需下载数据集;我们将在工作示例中自动下载它。

下面的示例下载数据集并汇总其形状。

运行示例将下载数据集并将其分为输入和输出元素。正如预期的那样,我们可以看到有 351 行数据,其中包含 34 个输入变量。

我们可以使用重复分层交叉验证来评估该数据集上的支持向量机 (SVM) 模型。

我们可以报告数据集上模型的平均性能,该性能已在所有折叠和重复中平均,这将为后面部分进行的模型超参数调优提供参考。

完整的示例如下所示。

运行示例将首先加载和准备数据集,然后评估该数据集上的 SVM 模型。

注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能有所不同。可以考虑多次运行示例并比较平均结果。

在这种情况下,我们可以看到具有默认超参数的 SVM 达到了约 93.7% 的平均分类准确率,这非常出色,并且接近该问题的最佳性能 94%。

接下来,让我们看看是否可以通过使用 scikit-optimize 库调整模型超参数来提高性能。

手动调优算法超参数

Scikit-Optimize 库可用于调整机器学习模型的超参数。

我们可以通过使用该库的贝叶斯优化功能来手动实现。

这需要我们首先定义一个搜索空间。在这种情况下,这将是我们希望调整的模型超参数,以及每个超参数的范围或区间。

我们将调整以下 SVM 模型超参数

  • C,正则化参数。
  • kernel,模型中使用的核类型。
  • degree,用于多项式核。
  • gamma,用于大多数其他核。

对于数值超参数 *C* 和 *gamma*,我们将定义一个对数尺度来搜索 1e-6 到 100 之间的值。*degree* 是一个整数,我们将搜索 1 到 5 之间的值。最后,*kernel* 是一个具有特定命名值的分类变量。

我们可以定义这四个超参数的搜索空间,即 skopt 库中的数据类型列表,如下所示:

请注意为每个超参数指定的数据类型、范围和名称

然后,我们可以定义一个将被搜索过程调用的函数。这是优化过程稍后期望的函数,它接受一个模型和一组特定的模型超参数,对其进行评估,并为该超参数集返回一个分数。

在我们的例子中,我们希望使用重复分层 10 折交叉验证在我们的电离层数据集上评估模型。我们希望最大化分类准确率,即找到能获得最佳准确率的模型超参数集。默认情况下,该过程最小化此函数返回的分数,因此,我们将返回准确率减一,即完美技能将是 (1 – 准确率) 或 0.0,最差技能将是 1.0。

下面的 `evaluate_model()` 函数实现了这一点,并接受一组特定的超参数。

接下来,我们可以通过调用 `gp_minimize()` 函数并传递要调用以评估每个模型以及要优化的搜索空间的函数名称来执行搜索。

该过程将运行直到收敛并返回结果。

结果对象包含许多详细信息,但重要的是,我们可以访问最佳性能配置的分数以及最佳形成模型使用的超参数。

将这些整合在一起,在电离层数据集上手动调整 SVM 超参数的完整示例列在下面。

运行示例可能需要一些时间,具体取决于您的机器速度。

您可能会看到一些可以安全忽略的警告消息,例如

在运行结束时,将报告最佳性能配置。

注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能有所不同。可以考虑多次运行示例并比较平均结果。

在这种情况下,我们可以看到配置,按搜索空间列表的顺序报告,是适度的 *C* 值、RBF *kernel*、*degree* 为 2(RBF 核忽略)、以及适度的 *gamma* 值。

重要的是,我们可以看到此模型的技能约为 94.7%,这是一个表现出色的模型。

这并非使用 Scikit-Optimize 库进行超参数调优的唯一方法。在下一节中,我们可以看到一种更自动化的方法。

自动调优算法超参数

Scikit-Learn 机器学习库提供了用于调整模型超参数的工具。

具体来说,它提供了 GridSearchCVRandomizedSearchCV 类,它们接受模型、搜索空间和交叉验证配置。

这些类的优点是搜索过程是自动执行的,需要最少的配置。

同样,Scikit-Optimize 库通过 BayesSearchCV 类提供了类似的接口来执行模型超参数的贝叶斯优化。

此类的用法与 Scikit-Learn 等效类相同。

首先,搜索空间必须定义为字典,其中超参数名称用作键,变量范围用作值。

然后,我们可以定义 `BayesSearchCV` 配置,该配置接受我们希望评估的模型、超参数搜索空间以及交叉验证配置。

然后,我们可以执行搜索并在最后报告最佳结果和配置。

将这些整合在一起,使用 BayesSearchCV 类在电离层数据集上自动调整 SVM 超参数的完整示例列在下面。

运行示例可能需要一些时间,具体取决于您的机器速度。

您可能会看到一些可以安全忽略的警告消息,例如

在运行结束时,将报告最佳性能配置。

注意:由于算法或评估程序的随机性,或数值精度的差异,您的结果可能有所不同。可以考虑多次运行示例并比较平均结果。

在这种情况下,我们可以看到该模型表现优于表现最佳的模型,达到了约 95.2% 的平均分类准确率。

搜索发现了较大的 *C* 值、RBF *kernel* 和较小的 *gamma* 值。

这为您可以在机器学习项目中调整超参数提供了一个模板。

进一步阅读

如果您想深入了解,本节提供了更多关于该主题的资源。

相关教程

API

总结

在本教程中,您学习了如何使用 Scikit-Optimize 库使用贝叶斯优化进行超参数调优。

具体来说,你学到了:

  • Scikit-Optimize 提供了一个通用的贝叶斯优化工具包,可用于超参数调优。
  • 如何手动使用 Scikit-Optimize 库来调整机器学习模型的超参数。
  • 如何使用内置的 BayesSearchCV 类执行模型超参数调优。

你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。

发现 Python 中的快速机器学习!

Master Machine Learning With Python

在几分钟内开发您自己的模型

...只需几行 scikit-learn 代码

在我的新电子书中学习如何操作
精通 Python 机器学习

涵盖自学教程端到端项目,例如
加载数据可视化建模调优等等...

最终将机器学习带入
您自己的项目

跳过学术理论。只看结果。

查看内容

40 条回复关于*机器学习中的 Scikit-Optimize 超参数调优*

  1. Guillermo Wendorff 2020年9月4日 上午5:41 #

    太棒了 Jason,这看起来很有前途!
    再次感谢分享!

  2. Michael Kelly 2020年9月4日 上午7:19 #

    这真是个秘密武器。感谢您清晰的解释和示例代码。我喜欢它运行多线程。我在不到一分钟的时间内就收敛到了 0.955 的准确率。

  3. Carlos Augusto 2020年9月5日 上午3:22 #

    谢谢!精彩的解释!!

  4. Ameer 2020年9月5日 晚上11:59 #

    感谢 Jason 带来的精彩内容。
    我通过您的书籍学习了核心知识。
    确实令人惊叹。

  5. Tom 2020年9月6日 晚上11:38 #

    嗨,Jason,

    我在你的文本中发现了一个错误。

    在“机器学习数据集和模型”部分的末尾,您写道:

    “在这种情况下,我们可以看到具有默认超参数的 SVM 达到了约 83.7% 的平均分类准确率,这非常出色,并且接近该问题的最佳性能 94%。”

    但是,性能实际上是 0.937 而不是 0.837。

    我也通过自己实现您的代码进行了验证。

    因此,开箱即用的 SVM 的性能是 93.7 而不是 83.7。

    谢谢
    汤姆

  6. Sifa 2020年9月12日 上午11:17 #

    多么棒的秘密!
    感谢分享

  7. Anthony The Koala 2020年9月21日 上午2:33 #

    尊敬的Jason博士,
    这是一个关于在以后使用数据时依赖优化参数的问题。

    跳过背景信息。
    我的问题是关于运行程序几次 - (i) 是使用最低还是最高的准确率和相关的参数,(ii) 如果我有相似的准确率,是使用例如高 C 还是低 C?

    背景信息
    我运行了第二个模型两次

    您经常提到结果的“随机性”。

    知道微调的参数应该设置给哪个参数?是使用准确率为 0.866 的模型参数还是准确率为 0.951 的参数?

    但是,即使准确率为 0.951,相关的参数也与您的模型不同。

    举例说明

    也就是说,即使准确率非常相似,您的模型C值为4.87,而我的C值为26。同样,您的模型的degree为4,而我的模型degree为5。您的gamma是我的两倍多。

    问题

    总而言之:我应该使用哪个模型参数?是与最高准确率相关的参数,还是与最低准确率相关的参数?

    假设我有一些模型产生相似的准确率。我应该使用哪个关联的参数——C值最高还是C值最低?

    谢谢你,
    悉尼的Anthony

  8. Anthony The Koala 2020年9月22日下午2:10 #

    尊敬的Jason博士,
    我注意到您使用了两种不同的方法来定义四个超参数的搜索空间。

    在“手动调整算法参数”的小标题下,您为SVC的超参数搜索空间在第13-19行中设置为list()。

    相反,在“自动调整算法超参数”的小标题下,您在第14-19行中将超参数的搜索空间设置为字典。

    我认为使用字典方法设置参数搜索比list()方法更简单。

    我想弄清楚如何在“手动调整算法参数”下的代码第22-33行中使用字典方法而不是列表方法。

    仅仅用dict()替换list()会产生错误信息。

    为什么我不能使用dict()方法?它更简单,因为您不必像在https://scikit-optimize.github.io/stable/modules/generated/skopt.Space.html中所描述的那样,去关心使用Real、Categorical、Integer和Real设置。

    谢谢你,
    悉尼的Anthony

    • Jason Brownlee 2020年9月23日上午6:31 #

      这两种方法都使用了两个不同的API,并且不直接兼容。

      • Anthony The Koala 2020年9月23日下午2:09 #

        尊敬的Jason博士,
        感谢您的回复。
        悉尼的Anthony

  9. Anthony The Koala 2020年9月24日下午7:00 #

    尊敬的Jason博士,
    我有一个关于具有超参数的函数的问题。
    在您使用的示例中,SVC()函数具有一些超参数。
    您将超参数搜索列表设置为

    使用inspect方法,我能够找出SVC()的参数。

    问题:我想知道如何将SVC的签名与search_list关联起来。也就是说,如果我知道签名,我如何将其与设置搜索空间联系起来?我将举一个例子,希望能找到规律。
    例子。

    在SVC()的签名中

    从哪里可以获得设置1e-6、100、“log-uniform”这些与C相关的参数的信息?

    如果不是“log-uniform”,而是“binary”或“blahblahblah-distribution”呢?

    换句话说,如果我找到带有参数的函数,如何找到哪些参数是有效的/无效的,以及给定函数签名的参数范围?

    谢谢你,
    悉尼的Anthony

    • Anthony The Koala 2020年9月24日下午7:06 #

      尊敬的Jason博士,
      我想修改关于inspect.signature(SVC)的问题。

      再次,问题是,如果我有一个函数,它有很多参数需要调整,比如SVC(),我如何将函数的签名与设置超参数调优的search_space联系起来?
      例如,在SVC()的签名中,我有

      在搜索空间中,您有与“C”关联的搜索空间。

      页面https://scikit-optimize.github.io/stable/modules/generated/skopt.Space.html几乎没有将SVC()的函数签名与组织搜索空间联系起来。

      谢谢你,
      悉尼的Anthony

      • Jason Brownlee 2020年9月25日上午6:35 #

        C是一个正则化超参数,通常在log-10尺度上搜索正则化超参数。

    • Jason Brownlee 2020年9月25日上午6:34 #

      您可以在此处查看SVC模型支持的超参数的完整列表。
      https://scikit-learn.cn/stable/modules/generated/sklearn.svm.SVC.html

      我根据我对算法工作原理/超参数作用的了解,为每个超参数选择了不同的范围。

      是的,您可以选择不同的超参数进行调整和不同的分布。放手去做吧!

      例如,本教程提供了更多关于机器学习算法常用超参数的信息。
      https://machinelearning.org.cn/hyperparameters-for-classification-machine-learning-algorithms/

  10. ionut 2020年11月6日凌晨1:17 #

    我们如何使用使用BayesSearchCV的自动版本来优化ROC-AUC(最大化)或CrossEntropy(最小化)模型?

  11. Syamil 2021年2月15日下午6:45 #

    嗨,我总是收到错误。它显示

    __init__() got an unexpected keyword argument ‘iid’

    我搜索了解决方案,发现iid参数在sklearn的当前版本中已弃用。如何解决这个问题?
    谢谢

    • Jason Brownlee 2021年2月16日上午6:03 #

      也许从您的示例中删除该参数?

      也许确保您的库是最新的?

  12. Roi 2021年4月5日晚上9:58 #

    嘿 Jason,我如何使用skopt为回归问题实现调优?

    • Jason Brownlee 2021年4月6日上午5:17 #

      也许您可以尝试改编上面的例子——如果skopt支持回归的话,我猜是的。

  13. Mark 2021年4月11日晚上11:12 #

    嗨,Jason,

    非常感谢这个教程。我不知道有这样一个易于使用的模块(skopt),这使得实现贝叶斯优化变得简单。

    现在scikit-learn v0.24已经发布,它引入了与BayesSearchCV的不兼容性。后者默认传递一个iid=True参数,但scikit-learn不再接受它:https://github.com/scikit-optimize/scikit-optimize/issues/978
    在scikit-optimize被修改为兼容之前,有必要将scikit-learn降级到0.23.2版本。

    请考虑在您的描述中添加这样的说明。

  14. Adarsh 2021年6月24日凌晨12:26 #

    嗨,Jason,

    这两种方法(手动和自动)最终做的是同样的事情吗?它们是否在底层使用了相同的算法,只是API不同?我们能从两种API中期望相同的结果集吗?

    此致,
    Adarsh

  15. Lukas K 2021年9月23日晚上10:24 #

    感谢Jason的精彩文章,我目前正面临一个问题,我需要调整不仅是分类器的超参数,还有在分类器运行之前的第二个算法的超参数。

    所有scikit-learn的方法似乎只调整估计器的参数,就像这里使用的BayesSearchCV一样。对于其他问题,我可以使用transformers并将它们与估计器一起链接到标准的CV算法中。

    但是我的问题在于主动学习领域,我的第一个算法选择要训练的行,然后再拟合估计器。但是sklearn transformers不能增强行,因为它们只将X传递给估计器。但是如果我只使用一部分行,我也需要改变y,而sklearn pipelines做不到。

    forest_minimize()似乎是解决这个问题的候选方案,因为在我看来,您调用的evaluate_model()目标函数可以接受任何任意脚本并调整其所有参数。
    但是这个脚本在没有交叉验证的情况下工作,而交叉验证是很重要的。
    您是否看到我可以用(嵌套的)cv包装上面显示的手动方法?

    • Adrian Tam
      Adrian Tam 2021年9月24日上午4:48 #

      简要阅读您的描述,似乎您想构建一个pipeline来连接所有您需要的东西。请查看scikit-learn中的pipeline函数。它应该能给您一些启示。

  16. Sabastian Simbarashe Mukonza 2021年10月7日下午3:44 #

    嗨,Jason
    一如既往的好文章,如果可能的话,我该如何为SVR实现类似的超参数优化?

    • Adrian Tam
      Adrian Tam 2021年10月12日凌晨12:18 #

      理论上是可能的。您打算在这里做什么?

  17. Abdalsamad Keramatfar 2021年12月29日晚上6:48 #

    感谢您提供的精彩教程!您的网站是我的第二个stackoverfow!
    您能否请澄清一下“top performing”(表现最佳)这个句子:“A top performing model can achieve accuracy on this same test harness of about 94 percent.”(一个表现最佳的模型在此测试套件上可达到约94%的准确率)。是否有任何记分牌或者其他东西?

  18. Lekha 2023年2月15日上午9:09 #

    嗨 Jason。谢谢你的教程。我有一个问题。使用scikit optimize,在合理的函数调用次数(例如10000次)下,可以优化多少个超参数?

留下回复

Machine Learning Mastery 是 Guiding Tech Media 的一部分,Guiding Tech Media 是一家领先的数字媒体出版商,专注于帮助人们了解技术。访问我们的公司网站以了解更多关于我们的使命和团队的信息。