使用 Python 进行贝叶斯优化

 

一、介绍

        贝叶斯优化是一种先进的技术,用于优化评估成本高昂的函数。该策略为全局优化提供了原则性策略,强调探索(尝试新领域)和开发(尝试看起来有前途的领域)之间的平衡。

二、什么是贝叶斯优化?

贝叶斯优化的核心是一种基于概率模型的优化技术。它利用过去的评估结果形成概率模型,预测最佳解决方案可能位于何处。这里的关键是探索未知领域(我们尚未评估的功能领域)和开发已知区域(我们已经评估过并且看起来有前途的领域)之间的平衡。

简而言之,贝叶斯优化将我们过去的知识(评估)与不确定性(我们尚未评估的地方)结合起来,以对最佳解决方案可能位于何处做出有根据的猜测。

三、贝叶斯优化的组成部分

  1. 目标函数:这是我们要优化的函数。在许多现实问题中,评估目标函数可能需要大量计算、耗时或资源密集型。对于我们的示例,我们的目标函数是使用给定的超参数训练模型并返回其性能。
  2. 概率模型:贝叶斯优化使用概率模型来估计函数。通常使用高斯过程 (GP),因为它们不仅提供每个点的平均预测,而且还量化该预测的不确定性(方差)。
  3. 采集功能:该功能指导优化过程。它使用 GP 提供的均值和方差来建议目标函数中要评估的下一个点。常见的获取函数包括预期改进 (EI)、改进概率 (PI) 和置信上限 (UCB)。对于我们的示例,我们使用了预期改进函数。
  4. 贝叶斯优化循环:这是一个迭代过程,其中模型使用目标函数中的新数据点进行更新,并且采集函数建议下一个要评估的点。

四、Python 分步指南

        在本指南中,我们将使用 UCI 机器学习存储库中的葡萄酒质量数据集。

1. 下载数据集

下载数据集并将其保存到本地计算机。

2. 搭建环境

import numpy as np
import pandas as pd
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF, ConstantKernel as C
from scipy.optimize import minimize
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

3. 加载数据集

data = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv', sep=';')
X = data.drop('quality', axis=1)
y = data['quality']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

4. 贝叶斯优化

我们将尝试使用贝叶斯优化来优化简单回归器的超参数。

首先,我们将定义目标函数,它将使用给定的超参数训练模型并返回负均方误差(因为我们希望最大化质量预测精度)。

def objective_function(params):
    kernel = C(params[0], (1e-3, 1e3)) * RBF(params[1], (1e-2, 1e2))
    gp = GaussianProcessRegressor(kernel=kernel)
    gp.fit(X_train, y_train)
    predictions = gp.predict(X_test)
    return -mean_squared_error(y_test, predictions)

def objective_function(params):

        这定义了一个名为 的函数objective_function,它采用单个参数params,该参数应该是包含参数的列表或类似数组的对象。

  kernel = C(params[0], (1e-3, 1e3)) * RBF(params[1], (1e-2, 1e2))

        这里,正在构建高斯过程内核。该内核是两个组件的组合:

  1. 常数核 ( C):该核表示常数值,通常在高斯过程中用于定义常数缩放因子。它使用一个值进行初始化params[0],范围在 1×10−31×10−3 和 1×1031×103 之间。
  2. 径向基函数核 ( RBF):这是高斯过程中最常用的核之一。它决定了函数的形状或平滑度。它使用一个值进行初始化params[1],范围在 1×10−21×10−2 和 1×1021×102 之间。

        最终的内核是这两个内核的乘积,这是高斯过程中结合多个内核的效果的常见做法。

  gp = GaussianProcessRegressor(kernel=kernel)

        在这里,来自 scikit-learn 库的高斯过程回归器模型正在使用先前定义的内核进行初始化。

  gp.fit(X_train, y_train)

        高斯过程回归器模型正在训练数据X_train和上进行训练y_train

        predictions = gp.predict(X_test)

模型经过训练后,将用于对测试数据进行预测X_test。结果存储在变量中predictions

        return -mean_squared_error(y_test, predictions)

  y_test该函数最终返回真实测试值和预测值之间的负均方误差predictions。返回负值的原因是贝叶斯优化通常设置为最大化目标函数。通过返回负均方误差,优化过程将尝试找到给出最小误差(或最大负误差)的参数。

        本质上,这objective_function是为了评估具有给定内核配置的高斯过程回归器的性能(均方误差)。目标是找到最小化该误差的内核参数,并且该函数将用作贝叶斯优化过程的目标。

        现在,我们将定义获取函数:

def acquisition_function(x):
    # Expected Improvement acquisition function
    mu, sigma = gp.predict(x, return_std=True)
    return -(mu + 1.96 * sigma)

def acquisition_function(x):

这定义了一个名为 的函数acquisition_function,它采用单个参数x,它代表我们要评估采集函数的数据点(或点集)。

mu, sigma = gp.predict(x, return_std=True)

此处,高斯过程模型gp用于预测给定数据点 的平均值 ( mu) 和标准差 ( ) 。该参数确保该方法返回预测的标准差,该标准差量化了模型对该预测的不确定性。sigmaxreturn_std=True

在贝叶斯优化的背景下:

  • mu表示模型对 点 处目标函数值的最佳猜测x
  • sigma代表模型对该猜测的不确定性。越大sigma表示不确定性越高。

return -(mu + 1.96 * sigma)

mu该行返回和 1.96×1.96× σ之和的负数。

术语 1.96×1.96× σ本质上捕获高斯分布 95% 置信区间的上限。值 1.96 是 z 分数,对应于标准正态分布的第 97.5 个百分位(假设它是对称的)。

在获取函数的上下文中,这行代码可以解释如下:

  1. 探索与利用:获取函数在探索(高不确定性区域)和利用(低预测目标函数值区域)之间取得平衡。通过考虑mu(预测值)和sigma(不确定性),获取函数旨在探索有希望(低mu)或不确定(高sigma)的领域。
  2. 最大化框架:负号确保我们为最大化问题做好准备。预测值较低(负mu)或不确定性较高(正 1.96×1.96× σ)的区域将具有较高(负值较小)的采集函数值,使它们在贝叶斯优化的下一次迭代中更有吸引力。
  3. 95% 置信区间:因子 1.96 表明该函数将目标函数的值考虑到其 95% 置信区间的上限。这意味着采集函数在其探索中考虑“最坏情况”场景,查看目标函数的真实值可能高达 的点mu + 1.96 * sigma

本质上,acquisition_function量化了在 点评估目标函数的潜在收益x。它在模型不确定的探索点和模型预测低目标函数值的利用点之间取得平衡(假设我们正在处理最小化问题,如负号所示)。

最后,运行贝叶斯优化循环:

best_params = [1, 1]  # initial guess
for iteration in range(10):  # 10 iterations for demonstration purposes
    res = minimize(fun=objective_function, x0=best_params, bounds=[(1e-3, 1e3), (1e-2, 1e2)])
    best_params = res.x

best_params = [1, 1] # initial guess

此行初始化一个以两个值命名的列表best_params,均设置为 1。此列表表示我们要优化的参数的初始猜测。在前面讨论的上下文中,这些参数可能与高斯过程的内核相关,但它们通常可以是我们想要优化的任何参数。

for iteration in range(10): # 10 iterations for demonstration purposes

该行启动一个将运行 10 次的 for 循环。该循环的每次迭代都代表着寻找更好的参数集的优化尝试。

res = minimize(fun=objective_function, x0=best_params, bounds=[(1e-3, 1e3), (1e-2, 1e2)])

在这里,minimize函数(通常来自像 之类的库scipy.optimize)用于尝试找到最小化给定 的参数objective_function

  • fun=objective_function:这表明我们试图最小化的函数是objective_function
  • x0=best_params:这将优化的起点设置为我们当前对参数的最佳猜测。在第一次迭代中,这将是 [1, 1],但在后续迭代中,它将是上一次迭代中找到的最佳参数。
  • bounds=[(1e-3, 1e3), (1e-2, 1e2)]:这对参数可以采用的值设置限制。第一个参数被限制在 1×10−31×10−3 和 1×1031×103 之间,第二个参数被限制在 1×10−21×10−2 和 1×1021×102 之间。
  • 在这些迭代结束时,best_params应该包含葡萄酒质量数据集上高斯过程模型的优化超参数。

五、使用优化参数

一旦我们通过贝叶斯优化找到了优化参数,我们现在就可以将它们用于未来的预测。以下是如何加载具有优化超参数的模型并进行预测:

# Load the model with optimized parameters
optimized_kernel = C(best_params[0], (1e-3, 1e3)) * RBF(best_params[1], (1e-2, 1e2))
optimized_gp = GaussianProcessRegressor(kernel=optimized_kernel)
optimized_gp.fit(X_train, y_train)

# Making predictions
predictions = optimized_gp.predict(X_test)

结论

贝叶斯优化提供了一种结构化且有效的方法,通过从过去的评估中学习来找到问题的最佳解决方案。通过平衡探索和利用,它确保搜索既广泛(涵盖各种可能性)又深入(扩大到有希望的领域)。借助 Python 强大的库,该技术的实现变得简单直观。

参考

六、附录

对于那些寻求更简化方法的人来说,该bayesian-optimization库提供了一种运行贝叶斯优化的简单方法,而无需涉及复杂的高斯过程或采集函数。

1. 安装

首先,使用 pip 安装库:

!pip install bayesian-optimization

2. 搭建环境

from bayes_opt import BayesianOptimization
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF, ConstantKernel as C

3. 加载数据集

data = pd.read_csv('winequality-red.csv', sep=';')
X = data.drop('quality', axis=1)
y = data['quality']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

4. 目标函数

该库需要参数的范围作为输入。它将在这些范围内自动探索和利用。

def objective_function(C, RBF_length_scale):
    kernel = C * RBF(RBF_length_scale)
    gp = GaussianProcessRegressor(kernel=kernel)
    gp.fit(X_train, y_train)
    predictions = gp.predict(X_test)
    return -mean_squared_error(y_test, predictions)

5. 运行贝叶斯优化

# Defining bounds for the hyperparameters
pbounds = {
    'C': (1e-3, 1e3),
    'RBF_length_scale': (1e-2, 1e2)
}

optimizer = BayesianOptimization(
    f=objective_function,
    pbounds=pbounds,
    random_state=42
)

optimizer.maximize(
    init_points=2,  # Random exploratory steps
    n_iter=10       # Steps of Bayesian Optimization
)

.maximize函数将运行优化,完成后,可以使用以下方法检索最佳参数:

best_params = optimizer.max['params']

6. 使用优化参数

# Load the model with optimized parameters
optimized_kernel = C(best_params['C']) * RBF(best_params['RBF_length_scale'])
optimized_gp = GaussianProcessRegressor(kernel=optimized_kernel)
optimized_gp.fit(X_train, y_train)

# Making predictions
predictions = optimized_gp.predict(X_test)

七、结论

        该bayesian-optimization库提供了一种快速有效的方法来执行贝叶斯优化,而无需深入研究其复杂的数学知识。通过抽象复杂性,它使优化过程更易于访问和用户友好。

猜你喜欢

转载自blog.csdn.net/gongdiwudu/article/details/135392672
今日推荐