利用贝叶斯超参数优化,提升模型效果更科学(附Python代码)

news2024/12/25 12:39:46

超参数优化在大多数机器学习流水线中已成为必不可少的一步,而贝叶斯优化则是最为广为人知的一种“学习”超参数优化方法。

超参数优化的任务旨在帮助选择学习算法中成本(或目标)函数的一组最佳参数。这些参数可以是数据驱动的(例如,各种训练数据组合)或模型驱动的(例如神经网络中的层数、学习率、优化器、批处理大小等)。在具有深度架构的最先进复杂机器学习模型中,由于参数的组合数以及这些参数之间的相互作用,超参数优化并不是一个简单的计算任务。

在本文中,我们将讨论贝叶斯优化作为一种具有记忆并从每次参数调整中学习的超参数优化方法。然后,我们将从头开始构建一个贝叶斯优化器,而不使用任何特定的库。

1. 为什么使用贝叶斯优化

传统的超参数优化方法,如网格搜索(grid search)随机搜索(random search),需要多次计算给定模型的成本函数,以找到超参数的最优组合。由于许多现代机器学习架构包含大量超参数(例如深度神经网络),计算成本函数变得计算昂贵,降低了传统方法(如网格搜索)的吸引力。在这种情况下,贝叶斯优化已成为常见的超参数优化方法之一,因为它能够在迭代次数明显较少的情况下找到优化的解决方案,相较于传统方法如网格搜索和随机搜索,这得益于从每次迭代中学习。

2. 贝叶斯优化的工作原理

贝叶斯优化在概念上可能看起来复杂,但一旦实现,它会变得更简单。在这一部分中,我将提供贝叶斯优化工作原理的概念性概述,然后我们将实施它以更好地理解。

贝叶斯优化利用贝叶斯技术目标函数设置先验,然后添加一些新信息以得到后验函数

先验表示在新信息可用之前我们所知道的内容,后验表示在给定新信息后我们对目标函数的了解。

更具体地说,收集搜索空间的样本(在这个上下文中是一组超参数),然后为给定样本计算目标函数(即训练和评估模型)。由于目标函数不容易获得,使用“替代函数”作为目标函数的贝叶斯近似

然后,使用前一个样本的信息更新替代函数,从先验到后验。

后验表示在那个时间点上我们对目标函数的最佳了解,并用于指导“获取函数”获取函数(例如期望改进)优化搜索空间内位置的条件概率,以获取更有可能优化原始成本函数的新样本。

继续使用期望改进的例子,获取函数计算超参数网格中每个点的期望改进,并返回具有最大值的点。然后,新收集的样本将通过成本函数运行,后验将被更新,这个过程重复,直到达到目标函数的可接受的优化点、产生足够好的结果,或者资源耗尽。

3. 实现

本节将专注于贝叶斯优化的逐步实现,共有七个步骤。首先,我将列出这些步骤,然后提供详细的解释,以及实现代码块。

  • 导入库

  • 定义目标(或成本)函数

  • 定义参数边界

  • 定义获取函数

  • 初始化样本和替代函数

  • 运行贝叶斯优化循环

  • 返回结果

技术交流&材料获取

技术要学会分享、交流,不建议闭门造车。一个人可以走的很快、一堆人可以走的更远。

资料干货、资料分享、数据、技术交流提升,均可加交流群获取,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友。

方式①、添加微信号:dkl88194,备注:来自CSDN + 资料
方式②、微信搜索公众号:Python学习与数据挖掘,后台回复: 资料

1、数据分析实战宝典
在这里插入图片描述

2、100个超强算法模型

我们打造了《100个超强算法模型》,特点:从0到1轻松学习,原理、代码、案例应有尽有,所有的算法模型都是按照这样的节奏进行表述,所以是一套完完整整的案例库。

很多初学者是有这么一个痛点,就是案例,案例的完整性直接影响同学的兴致。因此,我整理了 100个最常见的算法模型,在你的学习路上助推一把!

在这里插入图片描述

让我们深入研究!

Step 1 — 导入库

我们首先导入一些必要的库,如下所示:

  • numpy 用于数值计算,是数据科学中常见的库之一

  • scipy.stats 是一个用于统计函数的库

  • load_irisscikit-learn 中加载鸢尾花数据集的函数

  • GaussianProcessRegressorscikit-learn 中实现高斯过程回归模型的类

  • Maternscikit-learn 中实现 Matern 核函数的类,用于高斯过程

import numpy as np
import scipy.stats as sps
from sklearn.datasets import load_iris
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import Matern

导入了这些库之后,让我们继续定义目标函数。

Step 2: 定义目标函数

目标函数接受一组超参数 Cgamma 作为输入,并返回在鸢尾花数据集上使用 RBF 核的支持向量分类器的负准确性。其中,C 是正则化参数,gammaRBFpolysigmoid 核的核系数。核系数的详细信息对我们的流程并不关键,可以在这里找到。然后,我们使用 load_iris 加载鸢尾花数据集,并将数据分为训练集和测试集。数据准备好后,训练支持向量分类器,并返回在测试集上的负准确性。

def objective(params):
    C, gamma = params
    X, y = load_iris(return_X_y=True)
    np.random.seed(0)
    indices = np.random.permutation(len(X))
    X_train = X[indices[:100]]
    y_train = y[indices[:100]]
    X_test = X[indices[100:]]
    y_test = y[indices[100:]]
    from sklearn.svm import SVC
    clf = SVC(C=C, gamma=gamma)
    clf.fit(X_train, y_train)
    return -clf.score(X_test, y_test)

Step 3: 定义参数边界

在这一步,我们定义超参数搜索空间的边界。我们创建一个形状为 (2, 2) 的 NumPy 数组 bounds,其中每行对应一个超参数,每列对应该超参数的下界和上界。在我们的例子中,第一个超参数是 C,第二个是 gamma,两者都用于训练支持向量分类器。

设置边界的目的是限制超参数搜索空间,避免测试不太可能是最优的值,并将优化焦点放在超参数空间的最有希望的区域。我们对这个练习随机定义了边界,但在超参数范围已知的任务中,这变得很重要。

bounds = np.array([[1e-3, 1e3], [1e-5, 1e-1]])

Step 4: 定义获取函数

这一步定义了我们之前讨论过的获取函数,并确定在搜索空间中要评估的下一个点。在这个具体的例子中,获取函数是期望改进(Expected Improvement, EI)函数。它测量目标函数在当前最佳观测值的基础上的期望改进,考虑到当前替代模型(高斯过程)。获取函数的定义如下:

  • 高斯过程使用 gp.predict() 在点 x 处预测均值和标准差。

  • 函数找到迄今为止观察到的最佳目标函数值(f_best)。

  • 计算对 f_best 的改进为 improvement = f_best — mu

  • 如果 sigma 为正,则计算标准得分 Z = improvement/sigma;如果 sigma0,则将 Z 设置为 0

  • 使用标准正态分布的累积分布函数(sps.norm.cdf)和概率密度函数(sps.norm.pdf)计算在点 x 处的期望改进(ei)。

  • 返回期望改进。

def acquisition(x):
    mu, sigma = gp.predict(x.reshape(1, -1), return_std=True)
    f_best = np.min(y_samples)
    improvement = f_best - mu
    with np.errstate(divide='warn'):
        Z = improvement / sigma if sigma > 0 else 0
        ei = improvement * sps.norm.cdf(Z) + sigma * sps.norm.pdf(Z)
        ei[sigma == 0.0] == 0.0
    return ei

Step 5: 初始化样本和替代函数

在开始贝叶斯优化循环之前,我们需要使用一些初始样本初始化高斯过程替代模型。如前所述,替代函数用于有效地逼近未知的目标函数以进行优化。高斯过程是一个概率模型,定义了对函数的先验。随着获取新数据,它允许使用贝叶斯推理来更新模型。具体而言,x_samples 是从由 bounds 数组定义的搜索空间中随机抽样的初始点。y_samples 是这些初始点对应的目标函数评估。这些样本用于训练高斯过程,并改进其替代建模。

Step 6: 运行贝叶斯优化循环

我们终于来到了贝叶斯优化循环。在这一步中,贝叶斯优化循环将运行指定次数(n_iter)。在每次迭代中,使用现有样本(即 x_samplesy_samples)更新高斯过程模型,使用 gp.fit() 方法。然后,通过在参数空间生成的大量随机点(即 x_random_points)优化获取函数,选择下一个由目标函数评估的样本。在这些点上评估获取函数,并选择获取函数值最大的点作为下一个样本(即 x_next)。在此点记录获取函数值作为 best_acq_value。最后,在选择的点上评估目标函数,并通过更新 x_samplesy_samples 将结果值添加到现有样本中。这个过程重复进行指定次数的迭代(即 n_iter),并打印每次迭代的结果。

# 运行 n_iter 次的贝叶斯优化循环
n_iter = 10
for i in range(n_iter):
    # 使用现有样本更新高斯过程
    gp.fit(x_samples, y_samples)

    # 通过优化获取函数找到下一个样本
    x_next = None
    best_acq_value = -np.inf

    # 从参数空间中抽样大量随机点
    n_random_points = 10000
    x_random_points = np.random.uniform(bounds[:, 0], bounds[:, 1], size=(n_random_points, bounds.shape[0]))

    # 在每个点上评估获取函数并找到最大值
    acq_values = np.array([acquisition(x) for x in x_random_points])
    max_acq_index = np.argmax(acq_values)
    max_acq_value = acq_values[max_acq_index]

    if max_acq_value > best_acq_value:
        best_acq_value = max_acq_value
        x_next = x_random_points[max_acq_index]

    print(f"Iteration {i+1}: next sample is {x_next}, acquisition value is {best_acq_value}")

    # 在下一个样本上评估目标函数并将其添加到现有样本中
    y_next = objective(x_next)
    x_samples = np.vstack((x_samples, x_next))
    y_samples = np.append(y_samples, y_next)

Step 7: 打印结果

最后,我们打印在贝叶斯优化循环中找到的最佳参数和最佳准确性。最佳参数是与目标函数最小值相对应的参数,这就是为什么使用 np.argmin 来找到 y_samples 最小值的索引。

# Print final results   
best_index = np.argmin(y_samples)   
best_x = x_samples[best_index]   
best_y = y_samples[best_index]   

print(f"Best parameters: C={best_x[0]}, gamma={best_x[1]}")   
print(f"Best accuracy: {best_y}")

以下是运行此过程的最终结果:

图片

4. 结论

在本文中,我们介绍了机器学习流水线中的超参数优化,并深入探讨了超参数优化的世界,详细讨论了贝叶斯优化以及为什么它可能是一种相对于基本优化器(如网格搜索和随机搜索)更有效的微调策略。然后,我们逐步从头开始构建了一个用于分类的贝叶斯优化器,以更好地理解这个过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1303158.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java项目-瑞吉外卖Day5

视线新增套餐功能: 创建SetmealDish,SetmealDto类,与相关的mapper,service,serviceImpl,controller类。 Setmeal表示套餐,SetmealDish表示套餐对应的菜品。 交互过程: 前端请求&a…

【每日一题】最小体力消耗路径

文章目录 Tag题目来源解题思路方法一:二分枚举答案 写在最后 Tag 【二分枚举答案】【图】【2023-12-11】 题目来源 1631. 最小体力消耗路径 解题思路 拿到这个题目,计算从左上角到右下角的最小体力消耗值,有点像 64. 最小路径和。在 64 题…

FFmpeg的AVIOPROBE

文章目录 定义 可能你一直有疑问,ffmpeg的avformat是怎么提前知道码流是编码格式或者容器?恭喜你,看到这里,你找到答案了,在这里,ffmpeg通过这些probe函数来提前获取码流的编码格式。 看到下面的avs2_prob…

EasyExcel-最简单的读写excel工具类

前言&#xff1a; easyExcel 的官网文档给的示例非常全&#xff0c;可以参考https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read 在此我贴出自己的工具类&#xff0c;可以直接用 导包 <dependency><groupId>com.alibaba</groupId><…

【基础知识】大数据概述

关键词—分布式 化整为零&#xff0c;再化零为整 大数据的定义 传统数据库处理起来困难的数据集。 发展历程 中国开源生态图谱2023 参考内容 中国开源生态图谱 2023.pdf 技术组件说明 数据集成 sqoop、dataX、flume 数据存储 hdfs、kafka 数据处理 mapreduce、hive…

Vue快速入门教程

什么是Vue&#xff1f; 1&#xff0c;vue是一套前端框架&#xff0c;免除原生JavaScrip中dom操作&#xff0c;简化书写。 2&#xff0c;给予MVVM&#xff08;Model-View-ViewModel&#xff09;思想&#xff0c;实现数据的双向绑定&#xff0c;将编程的关注点放在数据上 官网&a…

jvs智能bi新增:数据集添加sql自定义节点、添加websocket任务进度动态展示等等

智能bi更新功能 新增: 1.数据集添加sql自定义输入节点&#xff0c;支持mysql Oracle数据源&#xff1b; 用户可以从这些数据源中获取数据&#xff0c;并通过SQL语句对数据进行自定义处理和分析。可以帮助用户更加灵活地处理和分析数据&#xff0c;满足各种个性化的需求。 2.…

Hive的metastore服务的两种运行模式

Hive的metastore服务的作用是为Hive CLI或者Hiveserver2提供元数据访问接口 1.metastore运行模式 metastore有两种运行模式&#xff0c;分别为嵌入式模式和独立服务模式。下面分别对两种模式进行说明&#xff1a; &#xff08;1&#xff09;嵌入式模式 &#xff08;2&#x…

基于ssm网上医院预约挂号系统+jsp论文

摘 要 如今的信息时代&#xff0c;对信息的共享性&#xff0c;信息的流通性有着较高要求&#xff0c;因此传统管理方式就不适合。为了让医院预约挂号信息的管理模式进行升级&#xff0c;也为了更好的维护医院预约挂号信息&#xff0c;网上医院预约挂号系统的开发运用就显得很有…

基于SpringBoot+Vue社区医院服务系统(Java毕业设计)

点击咨询源码 大家好&#xff0c;我是DeBug&#xff0c;很高兴你能来阅读&#xff01;作为一名热爱编程的程序员&#xff0c;我希望通过这些教学笔记与大家分享我的编程经验和知识。在这里&#xff0c;我将会结合实际项目经验&#xff0c;分享编程技巧、最佳实践以及解决问题的…

代码随想录算法训练营第三十八天|理论基础、509.斐波那契数、70.爬楼梯、746.使用最小花费爬楼梯

代码随想录 (programmercarl.com) 理论基础 一、题目类型&#xff1a; 动规基础、背包问题、打家劫舍、股票买卖、子序列问题 二、解题思路&#xff1a; 动态规划五部曲&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始…

yolov8安装过程中问题总结

1、ImportError: DLL load failed while importing _imaging: 找不到指定的模块。 解决办法&#xff1a; 卸载当前pillow版本&#xff0c;安装6.2.1版本 pip uninstall pillowpip install pillow6.2.1 -i https://pypi.tuna.tsinghua.edu.cn/simple/2、No module named“req…

[面试篇~Spring] 必问基础知识

文章目录 1. 什么是 Spring2. Spring 框架有哪些主要的模块&#xff1f;3. 使用 Spring 框架能带来哪些好处&#xff1f;4. 什么是控制反转5. 什么是依赖注入6. 为什么使用依赖注入7. 在 Java 中依赖注入有哪几种方式8. 请解释下 Spring 框架中的 IoC&#xff1f;9. BeanFactor…

大数据讲课笔记1.4 进程管理

文章目录 零、学习目标一、导入新课二、新课讲解&#xff08;一&#xff09;进程概述1、基本概念2、三维度看待进程3、引入多道编程模型&#xff08;1&#xff09;CPU利用率与进程数关系&#xff08;2&#xff09;从三个视角看多进程 4、进程的产生和消亡&#xff08;1&#xf…

go 编译apk

首先进行安装go 安装 wget https://studygolang.com/dl/golang/go1.21.5.linux-amd64.tar.gz tar zxvf go1.21.5.linux-amd64.tar.gz mv go /usr/local/ vim /etc/profile # 进行配置环境变量&#xff1a; export GOROOT/usr/local/go export PATH$PATH:$GOROOT/bin # 保存退…

算法Day28 二进制差异序列(格雷码)

二进制差异序列&#xff08;格雷码&#xff09; Description n 位二进制差异序列是一个由2^n个整数组成的序列&#xff0c;其中&#xff1a; 每个整数都在范围[0, 2^n - 1]内&#xff08;含0和2^n - 1&#xff09; 第一个整数是0 一个整数在序列中出现不超过一次 每对相邻整数…

LeetCode-1008. 前序遍历构造二叉搜索树【栈 树 二叉搜索树 数组 二叉树 单调栈】

LeetCode-1008. 前序遍历构造二叉搜索树【栈 树 二叉搜索树 数组 二叉树 单调栈】 题目描述&#xff1a;解题思路一&#xff1a;题目大致意思就是给定一个二叉树的前序遍历&#xff0c;求对应的二叉搜索树。一种比较特殊的点是「二叉搜索树」的中序遍历的结果是【有序序列】&am…

参数占位符#{}和${}

#是预处理而$是直接替换 Mybatis在处理#{}时&#xff0c;会将SQL中的#{}替换成占位符&#xff1f;&#xff0c;再使用preparedStatement的set方法来赋值。而Mybatis在处理 时&#xff0c;是将 {}时&#xff0c;是将 时&#xff0c;是将{}直接替换成变量的值 我们分别使用#{}和…

热电厂发电机组常见故障及预测性维护方法

热电厂的发电机组是关键的能源生产设备&#xff0c;在电力供应中扮演着关键角色。但经过长期运行和高负荷工作&#xff0c;一旦发生故障&#xff0c;可能导致停机、设备损坏甚至引发严重事故。因此&#xff0c;实施有效的预测性维护方法对于确保发电机组的稳定运行至关重要。本…

vue3封装接口

在src下面创建一个文件夹任意名称 我拿这个名字举例子了apiService 相当于创建一个新的文件 // 封装接口 // apiService.js import axios from axios;// 接口前缀 const API_BASE_URL 前缀;接口后缀export const registerUser async (fileData) > {try {const response …