贝叶斯优化:从第一性原理看黑盒函数的最优解

引言:不确定性中的理性决策

在科学与工程的广袤疆域中,我们常常面临一类极具挑战性的优化问题:目标函数 $f(x)$ 像是一个神秘的“黑盒子”。我们不知道它的解析形式,不知道它的梯度信息(或者梯度不存在),而且每一次评估(Evaluation)都极其昂贵——可能意味着训练一个深度神经网络数天,合成一种新材料数周,或者进行一次耗资巨大的物理实验。

传统的优化方法在此刻显得捉襟见肘:

  • 网格搜索(Grid Search):受制于维数灾难,效率低下。
  • 随机搜索(Random Search):缺乏记忆,无法利用历史信息指导未来探索。
  • 梯度下降(Gradient Descent):依赖导数,且容易陷入局部最优,不适用于离散或不可微的黑盒函数。

贝叶斯优化(Bayesian Optimization, BO) 应运而生。它不仅仅是一个算法,更是一种在有限预算下,平衡“已知”与“未知”的哲学体系

本文将从原理出发,解构贝叶斯优化如何利用高斯过程(Gaussian Processes) 构建世界模型,并通过采集函数(Acquisition Functions) 定最优策略,从而在探索(Exploration)与利用(Exploitation)之间找到完美的平衡。


第一性原理:黑盒优化的本质

优化的核心目标是找到输入 $x^*$,使得目标函数 $f(x)$ 取得全局最大值(或最小值):

$$
x^* = \arg \max_{x \in \mathcal{X}} f(x)
$$

在贝叶斯优化的语境下,我们假设 $f(x)$ 满足两个核心约束:

  1. 黑盒特性:我们只能通过输入 $x$ 观察到输出 $y$,且观测可能包含噪声,即 $y = f(x) + \epsilon$。
  2. 高昂成本:我们无法承担大量的采样,必须每一次尝试都“物有所值”。

贝叶斯思维:信念的更新

频率学派(Frequentist)视参数为固定常数,而贝叶斯学派(Bayesian)视参数为随机变量。在优化过程中,我们将 $f(x)$ 视为一个随机函数。

这就引入了贝叶斯推理的核心公式:

$$
P(f | \mathcal{D}) \propto P(\mathcal{D} | f) P(f)
$$

  • $P(f)$(先验,Prior):在观测任何数据之前,我们对函数形状的假设(例如,它应该是平滑的)。
  • $P(\mathcal{D} | f)$(似然,Likelihood):给定函数形态下,观测到当前数据的概率。
  • $P(f | \mathcal{D})$(后验,Posterior):结合了先验信念和观测数据后,我们对函数形态的最新认知。

贝叶斯优化的过程,就是不断收集数据 $\mathcal{D} = {(x_1, y_1), …, (x_n, y_n)}$,更新对 $f(x)$ 的后验分布,并据此决定下一个 $x_{n+1}$ 去哪里采样的过程。


代理模型:高斯过程(Gaussian Processes)

为了数学上可处理,我们需要一个能够描述“函数分布”的模型。高斯过程(GP) 是贝叶斯优化的标配代理模型(Surrogate Model)。

什么是高斯过程?

从物理直觉来看,高斯过程是多元高斯分布在无限维度的推广。如果说高斯分布描述的是标量的随机变量,那么高斯过程描述的就是随机函数

一个高斯过程由均值函数 $m(x)$ 和协方差函数(核函数)$k(x, x’)$ 唯一确定:

$$
f(x) \sim \mathcal{GP}(m(x), k(x, x’))
$$

核心机制:核函数(Kernel Function)

核函数 $k(x, x’)$ 定义了空间中两点之间的相似度,进而决定了函数的平滑性。常用的核函数是径向基函数(RBF)或平方指数核(Squared Exponential):

$$
k(x, x’) = \sigma^2 \exp\left( -\frac{||x - x’||^2}{2l^2} \right)
$$

这里蕴含着深刻的几何意义:

  • 如果 $x$ 和 $x’$ 很近,则 $k(x, x’) \to \sigma^2$,意味着这两个点的函数值 $f(x)$ 和 $f(x’)$ 具有很高的相关性。
  • 如果 $x$ 和 $x’$ 很远,则 $k(x, x’) \to 0$,意味着它们互不影响。

(图注:高斯过程后验分布示意图。实线为均值,阴影区域表示不确定性/方差。观测点附近的方差收缩为0,远离观测点的方差较大。)

后验推断(Math Heavy)

假设我们有观测数据 $X$ 和对应的函数值 $\mathbf{y}$,现在要预测新点 $x_*$ 的函数值 $f_*$。根据联合高斯分布性质:

$$
\begin{bmatrix} \mathbf{y} \ f_* \end{bmatrix} \sim \mathcal{N} \left( \mathbf{0}, \begin{bmatrix} K(X, X) + \sigma_n^2 I & K(X, x_*) \ K(x_*, X) & k(x_*, x_*) \end{bmatrix} \right)
$$

利用条件概率公式,我们可以得到 $f_*$ 的后验分布也是高斯分布,其均值 $\mu_*$ 和方差 $\sigma_*^2$ 为:

$$
\mu(x_*) = K(x_*, X) [K(X, X) + \sigma_n^2 I]^{-1} \mathbf{y}
$$

$$
\sigma^2(x_*) = k(x_*, x_*) - K(x_*, X) [K(X, X) + \sigma_n^2 I]^{-1} K(X, x_*)
$$

物理意义解读:

  • 预测均值 $\mu(x_*)$:这是模型认为 $f(x_*)$ 最可能的值,代表了**Exploitation(利用)**的基础。
  • 预测方差 $\sigma^2(x_*)$:这是模型对该点的不确定性,代表了**Exploration(探索)**的潜力。

决策引擎:采集函数(Acquisition Function)

有了代理模型(GP),我们知道了哪里可能值很高(高均值),哪里我们很不了解(高方差)。下一步由谁来做决定?这就引入了采集函数 $\alpha(x)$

采集函数的目标是将复杂的后验分布映射为一个简单的数值,该数值代表了在点 $x$ 处进行采样的“价值”。

$$
x_{n+1} = \arg \max_{x} \alpha(x; \mathcal{D}_n)
$$

1. Upper Confidence Bound (UCB) - 乐观主义者的选择

UCB 体现了“面对不确定性时的乐观原则”(Optimism in the face of uncertainty)。它直接线性组合了均值和标准差:

$$
\alpha_{UCB}(x) = \mu(x) + \kappa \cdot \sigma(x)
$$

  • $\mu(x)$:倾向于去已知表现好的地方(Exploitation)。
  • $\sigma(x)$:倾向于去未知的地方(Exploration)。
  • $\kappa$:调节参数。$\kappa$ 越大,越倾向于探索。

心理学视角:这就像一个寻宝者,不仅会去挖那些传说中有宝藏的地方(均值高),也会去挖那些从未涉足的荒地(方差大),因为那里可能隐藏着惊喜。

2. Expected Improvement (EI) - 风险中性者的选择

EI 关注的是:在这个点采样,预期能比当前的全局最优值 $f(x^+)$ 提升多少?

$$
\alpha_{EI}(x) = \mathbb{E} [ \max(f(x) - f(x^+), 0) ]
$$

通过推导,可以得到解析解:

$$
\alpha_{EI}(x) = (\mu(x) - f(x^+) - \xi)\Phi(Z) + \sigma(x)\phi(Z)
$$

其中 $Z = \frac{\mu(x) - f(x^+) - \xi}{\sigma(x)}$,$\Phi$ 和 $\phi$ 分别是标准正态分布的CDF和PDF。

EI 是目前最常用的采集函数,因为它在没有任何调节参数的情况下(除了微小的 $\xi$ 用于数值稳定性),就能在探索和利用之间取得极佳的平衡。


算法流程与代码实现

让我们将上述理论转化为算法流程:

  1. 初始化:随机采样若干点,构建初始数据集 $\mathcal{D}$。
  2. 循环(直到达到预算):
    a. 基于 $\mathcal{D}$ 拟合高斯过程(GP)。
    b. 在定义域内最大化采集函数 $\alpha(x)$,找到下一个采样点 $x_{next}$。
    c. 昂贵操作:计算真实的 $y_{next} = f(x_{next})$。
    d. 更新数据集 $\mathcal{D} = \mathcal{D} \cup {(x_{next}, y_{next})}$。
    e. 更新 GP 后验分布。
  3. 输出:历史上观测到的最优值。

以下是使用 Python 和 scikit-learn 实现的一个简化版贝叶斯优化器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import numpy as np
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import Matern
from scipy.stats import norm
from scipy.optimize import minimize

class SimpleBayesianOptimization:
def __init__(self, target_func, bounds):
self.target_func = target_func
self.bounds = bounds
# 使用 Matern 核函数,nu=2.5 允许适度的粗糙度
self.kernel = Matern(nu=2.5)
self.gp = GaussianProcessRegressor(kernel=self.kernel,
alpha=1e-6,
normalize_y=True)
self.X_sample = []
self.Y_sample = []

def _acquisition_function(self, x, xi=0.01):
"""
Expected Improvement (EI)
"""
mean, std = self.gp.predict(x.reshape(1, -1), return_std=True)
if len(self.Y_sample) == 0:
return 0

mu_sample_opt = np.max(self.Y_sample)

with np.errstate(divide='warn'):
imp = mean - mu_sample_opt - xi
Z = imp / std
ei = imp * norm.cdf(Z) + std * norm.pdf(Z)
ei[std == 0.0] = 0.0

return ei[0]

def propose_location(self, n_restarts=25):
"""
最大化采集函数以寻找下一个采样点
由于采集函数是非凸的,我们使用多次随机重启
"""
dim = self.bounds.shape[0]
min_val = 1
min_x = None

def min_obj(x):
return -self._acquisition_function(x)

# 随机重启优化
for x0 in np.random.uniform(self.bounds[:, 0], self.bounds[:, 1], size=(n_restarts, dim)):
res = minimize(min_obj, x0=x0, bounds=self.bounds, method='L-BFGS-B')
if res.fun < min_val:
min_val = res.fun[0]
min_x = res.x

return min_x.reshape(1, -1)

def optimize(self, n_iter=10):
# 初始随机采样
for _ in range(2):
x = np.random.uniform(self.bounds[:, 0], self.bounds[:, 1], size=(1, self.bounds.shape[0]))
y = self.target_func(x)
self.X_sample.append(x)
self.Y_sample.append(y)

self.X_sample = np.vstack(self.X_sample)
self.Y_sample = np.array(self.Y_sample)

for i in range(n_iter):
# 更新 GP
self.gp.fit(self.X_sample, self.Y_sample)

# 寻找下一个点
x_next = self.propose_location()

# 评估黑盒函数
y_next = self.target_func(x_next)

# 打印过程
print(f"Iteration {i+1}: x={x_next[0]}, y={y_next:.4f}")

# 添加数据
self.X_sample = np.vstack((self.X_sample, x_next))
self.Y_sample = np.append(self.Y_sample, y_next)

idx_best = np.argmax(self.Y_sample)
return self.X_sample[idx_best], self.Y_sample[idx_best]

# 示例使用:优化一个简单的 1D 函数
# f(x) = - (x - 2)^2 + 10
def black_box_function(x):
return -(x - 2)**2 + 10

# 运行优化
bo = SimpleBayesianOptimization(target_func=black_box_function,
bounds=np.array([[-5, 5]]))
best_x, best_y = bo.optimize(n_iter=5)
print(f"Optimal Result: x={best_x}, y={best_y}")

实际应用:从调参到材料科学

理解了原理,我们来看看贝叶斯优化如何在工业界大放异彩。

1. 机器学习超参数调优(AutoML)

这是 BO 最著名的应用场景。深度学习模型(如 Transformer, CNN)拥有海量的超参数(学习率、层数、Batch size、Dropout率)。

  • 问题:训练一次大模型可能耗资数千美元。网格搜索不可行。
  • BO 优势:BO 能够构建超参数与验证集准确率之间的响应面(Response Surface),快速收敛到最优配置。Google 的 Vizier 系统正是基于此原理。

2. A/B 测试与在线推荐

在互联网产品迭代中,我们可能需要测试不同的UI布局或推荐算法参数。

  • 问题:流量是金钱,不能把太多流量浪费在效果差的方案上。
  • BO 优势:通过 UCB 算法,系统可以自动且平滑地将流量倾斜到表现更好的版本上,同时保留少量流量探索新版本(Exploration-Exploitation Dilemma)。这与多臂老虎机(Multi-Armed Bandit)问题紧密相关。

3. 材料科学与药物发现

  • 问题:合成一种新合金或测试一种新药物分子的性质,需要实验室进行物理合成,周期长且成本极高。
  • BO 优势:科学家利用 BO 根据已有的实验数据,预测哪种化学成分配比最有可能产生高强度或高导电性的材料,指导下一次实验。这被称为“逆向设计”(Inverse Design)。

4. 机器人控制

  • 问题:机器人步态参数的微调。如果直接在物理机器人上随机试错,可能会导致机器人摔坏。
  • BO 优势:BO 可以在极少的试验次数内找到稳定的控制参数,并且可以通过设置安全约束(Safe Bayesian Optimization)来避免危险区域。

总结:理性的力量

贝叶斯优化之所以迷人,在于它将人类的认知过程数学化了。

当我们面对未知世界时,我们拥有过去的经验(先验 Prior);当我们尝试去探索时,我们获得了反馈(似然 Likelihood);进而我们修正了自己的世界观(后验 Posterior)。在这个过程中,我们既不盲目自信(过度利用),也不盲目乱撞(过度探索),而是根据**信息增益(Information Gain)**的最大化来指导行动。

从数学公式中的 $\sigma(x)$ 到现实生活中的风险投资,贝叶斯优化揭示了一个深刻的真理:最大的机会往往隐藏在不确定性最高的领域,但只有理性的探索者才能在有限的生命(Budget)中找到它。



贝叶斯优化:从第一性原理看黑盒函数的最优解
https://sunfove.xyz/2026/01/30/2026-01-30-bayesian-optimization-first-principles/
Author
Sunfove
Posted on
January 30, 2026
Licensed under