4. 代理模型入门

在实验优化中,真正昂贵的往往不是算法,而是每一次实验或仿真本身。代理模型(Surrogate Model)的作用,是用少量已完成的实验点,拟合出输入参数与响应之间的近似映射,从而在后续搜索中替代真实实验进行快速预测。本节聚焦三类最常用的响应面代理模型:高斯过程回归(GPR)、随机森林(RF)与神经网络(NN),重点讲清它们各自适合什么条件,以及如何用最小代码快速跑通。

一、三类代理模型的本质差异

理解适用条件,先要理解它们对数据的“假设”不同。

高斯过程回归把响应看作一个随机过程,任意有限个点的响应服从联合高斯分布,由均值函数和核函数(协方差函数)决定。核函数刻画“相近输入应有相近输出”的平滑程度。它的最大特点是自带不确定性估计:对每个预测点不仅给出均值,还给出方差。这使它天然适合贝叶斯优化中的采集函数(如EI、UCB)。代价是计算复杂度随样本数n约为O(n³),样本超过一两千后训练明显变慢。

随机森林由多棵决策树集成,每棵树在自助采样和随机特征子集上训练,最终取平均。它不假设平滑性,能自然处理非线性、特征交互和类别型变量,对异常值不敏感,几乎不需要调参就能得到稳健结果。缺点是预测在训练点之外趋于常数(外推能力弱),且不确定性估计不如GPR规范。

神经网络通过多层非线性变换拟合复杂函数,参数量大、表达能力强,适合高维、大样本、响应面高度复杂甚至不连续的场景。但它需要更多数据才能稳定,训练对学习率、网络结构、归一化敏感,且默认不提供可靠的不确定性。

三类代理模型:数据条件 → 模型选择 → 预测特性 数据条件 样本少 n ≤ 200 响应平滑 样本中等 n 数百~数千 含类别/噪声 样本充足 n ≥ 1000 高维/强非线性 需要不确定性 用于贝叶斯优化 采集函数决策 探索/利用权衡 候选模型 高斯过程回归 GPR 核函数:RBF / Matern 输出:均值 + 方差 复杂度 O(n³) 随机森林 RF 多棵决策树 + 自助采样 输出:均值(方差近似) 抗噪、抗过拟合 神经网络 NN MLP / 全连接层 输出:均值(需额外估计方差) 需归一化 + 调参 预测特性 内插准、外推弱 平滑响应面 不确定性可靠 适合小样本 稳健、易用 特征重要性可解释 外推趋于常数 适合含噪数据 表达力强 高维复杂映射 需大量数据 不确定性需额外处理

二、快速实现:以“反应产率优化”为例

假设我们优化一个化学反应的产率,两个输入变量:温度T(60~100℃)和催化剂用量C(0.5~2.0 mol%),响应为产率Y(%)。已有20组实验数据。下面用Python快速实现三种代理模型,并比较其交叉验证表现。

import numpy as np
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF, WhiteKernel
from sklearn.ensemble import RandomForestRegressor
from sklearn.neural_network import MLPRegressor
from sklearn.model_selection import cross_val_score, KFold
from sklearn.preprocessing import StandardScaler

# 示例数据(20组,仅作教学演示)
X = np.array([[70,1.0],[80,1.5],[90,0.8],[75,1.2],[85,1.8],
              [65,0.6],[95,1.4],[72,1.1],[88,1.6],[78,0.9],
              [82,1.3],[68,0.7],[92,1.7],[76,1.0],[86,1.5],
              [74,1.2],[84,0.8],[90,1.9],[66,0.5],[80,1.4]])
y = np.array([62,78,71,69,82,55,85,64,80,67,
              75,58,83,66,79,68,73,86,52,77])

# 标准化(NN和GPR对尺度敏感)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

kf = KFold(n_splits=5, shuffle=True, random_state=42)

# 1) GPR:RBF核 + 白噪声核
kernel = RBF(length_scale=1.0) + WhiteKernel(noise_level=1.0)
gpr = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=5, random_state=42)
gpr_scores = cross_val_score(gpr, X_scaled, y, cv=kf, scoring='r2')

# 2) 随机森林
rf = RandomForestRegressor(n_estimators=300, random_state=42)
rf_scores = cross_val_score(rf, X, y, cv=kf, scoring='r2')

# 3) 神经网络
nn = MLPRegressor(hidden_layer_sizes=(32,16), activation='relu',
                  max_iter=2000, random_state=42)
nn_scores = cross_val_score(nn, X_scaled, y, cv=kf, scoring='r2')

print("GPR  R2:", gpr_scores.mean().round(3))
print("RF   R2:", rf_scores.mean().round(3))
print("NN   R2:", nn_scores.mean().round(3))

在类似的小样本(n=20)、平滑响应面场景中,典型结果往往是GPR的交叉验证R²最高(示例中约0.85~0.92),RF次之(约0.78~0.88),NN因数据太少容易欠拟合或过拟合,R²波动较大(约0.60~0.85)。这些数值仅为教学示例,实际结果取决于数据本身。

三、如何根据条件选择模型

选择不是凭偏好,而是看三个维度:样本量、响应面平滑性、是否需要不确定性。

  • 样本少(n<200)且响应平滑:优先GPR。核函数选RBF或Matern,配合WhiteKernel吸收噪声。若用于贝叶斯优化,GPR的方差可直接驱动EI采集。
  • 样本中等、含类别变量或噪声大:优先RF。它不需要标准化,对异常点稳健,还能输出特征重要性,帮助判断哪些参数真正影响响应。
  • 样本充足(n>1000)、高维或强非线性:考虑NN。务必先标准化输入输出,用早停或交叉验证控制过拟合。若需要不确定性,可用MC Dropout或集成多个网络。
  • 不确定时:先跑RF作为基线,再用GPR对比。若两者R²接近且样本少,选GPR以获取方差;若RF明显更稳,则选RF。
实操建议:无论选哪种模型,都先用5折交叉验证的R²或RMSE评估,而不是只看训练集拟合。对GPR,观察优化后的length_scale:若过小说明响应面剧烈变化,可能不适合GPR;若过大说明模型过于平滑,可能欠拟合。

四、快速验证与结果判读

训练完成后,不要只看一个R²数字。建议做两件事:一是画出预测值 vs 真实值的散点图,理想情况应沿对角线分布;二是检查残差是否随预测值变化,若呈喇叭形说明存在异方差,可能需要变换响应或改用RF。

对于GPR,还可以输出预测方差,观察哪些区域方差大——这些区域正是实验设计下一步应该补充采样的位置。这正是代理模型驱动实验优化的核心逻辑:用模型的不确定性指导下一轮实验,而不是均匀撒点。

常见误区:用NN去拟合20个样本,然后抱怨结果差;或者用GPR处理明显不连续的响应面(如相变、失效阈值),导致预测严重失真。模型没有绝对好坏,只有与数据条件是否匹配。

小结:GPR适合小样本、平滑、需要不确定性的场景;RF适合中等样本、含噪、需要稳健和可解释性的场景;NN适合大样本、高维、强非线性的场景。快速实现时,统一用交叉验证比较,再结合预测图和残差图判断是否可用。下一轮实验前,先让代理模型告诉你“哪里最不确定”。