简介:一份基于MATLAB的贝叶斯优化示例代码,面向机器学习调参、仿真优化及工程试验设计等人群,针对目标函数评估昂贵、解析表达未知的黑盒问题提供高效求解方案。代码清晰演示了如何调用MATLAB内置的bayesopt函数,以高斯过程作为代理模型,并通过预期改进(EI)等获取策略确定下一评估点,在有限迭代中逼近全局最优,相比网格搜索或随机搜索可大幅降低计算开销。压缩包内共2个.m文件,主脚本负责定义优化问题、设置模型与获取策略参数并执行迭代;另一文件封装了待优化的目标函数,便于读者理解函数接口和替换自身问题。整个压缩包仅641B,结构简洁,适合快速研读与二次修改;该资源已吸引1299人学习下载,在超参数调优、仿真标定等场景中具有直接借鉴价值。通过此案例,使用者能够完整掌握贝叶斯优化从目标函数设计、参数配置、迭代运行到结果解析的整个流程,并可将代码套用于自己的优化任务,节省大量试验时间和计算资源。
1. 贝叶斯优化在 MATLAB 里不是黑匣子:这份案例包能直接改出你要的调参代码
贝叶斯优化在 MATLAB 里不是黑匣子:它把每次实验当成一次采样,用高斯过程拟合目标函数,再挑最有希望的点试下一次,回答的是"下一个参数该选哪"。这份案例包给的是能直接跑的 MATLAB 代码,不是公式截图。包里覆盖两条路线:官方 bayesopt 工具箱的完整调参流程,和不依赖工具箱、手写高斯过程与 EI 采集函数的实现。如果你正在用 MATLAB 调 SVM 的惩罚系数、神经网络的初始学习率,或者某个仿真模型的边界参数,这份代码能把"试参数"变成"算参数"。适合有 MATLAB 基础、没系统碰过贝叶斯优化的工程师和研究生,照着改目标函数就能跑通。
2. 先把机制讲透:代理模型与采集函数决定优化上限
很多人拿到代码的第一反应是删注释直接跑,跑完发现结果不如预期,问题往往不在代码,而在没搞懂两个核心部件:代理模型和采集函数。这两个东西决定了优化往哪个方向走、走得快还是慢。先讲清楚它们,后面改参数才知道自己在改什么。
2.1 高斯过程代理模型:为什么它比网格搜索聪明
贝叶斯优化的核心思路是用一个便宜的代理模型去逼近昂贵的目标函数。这里的"昂贵"指每次评估要花钱、花时间,比如跑一次仿真、做一次交叉验证。网格搜索和随机搜索都不利用历史信息:网格搜索是固定网格上穷举,维度一多点数爆炸;随机搜索虽然在高维时能救急,但完全不管"哪些点已经试过、哪些区域还没试"。贝叶斯优化不同,它把每次评估都记录下来,建立目标函数的后验估计,再根据这个估计选下一个点。
MATLAB 的 bayesopt 默认代理模型就是高斯过程回归,Statistics and Machine Learning Toolbox 里的 fitrgp 就是同一套模型。高斯过程和普通插值的关键区别在于:它不只给出每个点的预测均值,还给出预测方差。均值告诉你"这个点大概多好",方差告诉你"这个点的估计有多不确定"。采样稀疏的区域方差大,采样密集的区域方差小,这个不确定度图景正是贝叶斯优化用来决策的依据。
代理模型的具体形态由协方差函数(核函数)决定。bayesopt 默认用 ardmatematern52,也就是带 ARD(自动相关性确定)的 Matern 5/2 核。Matern 5/2 比平方指数核更"短尾",不会让远距离点之间还保持强相关,对变化剧烈的函数更稳;ARD 则是给每个输入维度学一个独立的长度尺度参数,自动判断哪个维度对目标值影响更大。这对调参场景非常关键——比如调 SVM 时,惩罚系数可能比核尺度敏感一个数量级,ARD 会把敏感维度的长度尺度压小,让采集函数在这一维多采样,不敏感维度少浪费评估次数。
提示:如果你的目标函数是确定性的(同一个点重复评估结果完全一样),GP 的噪声项会被压到接近 0;如果目标函数本身带随机性,一定要让模型知道噪声存在。这个开关在第 3 章和第 5 章会反复出现,是最容易踩的坑。
2.2 采集函数:EI、PI、UCB 怎么选
代理模型给了均值和方差之后,下一步是决定下一个采样点,这一步由采集函数完成。工具里有三个常用策略,参数名都能直接传给 bayesopt,先把差别摆出来:
| 采集函数 | 核心逻辑 | 适合场景 |
|---|---|---|
| expected-improvement | 最大化相对当前最优值的期望改进量 | 默认首选,探索和利用均衡 |
| expected-improvement-plus | EI 基础上对改进量停滞的区域加惩罚 | 防止长时间原地打转,bayesopt 默认 |
| probability-of-improvement | 只算改进的概率,不算改进的幅度 | 目标值有明确可接受阈值时 |
| upper-confidence-bound | 用 mu + kappa*sigma 选点,kappa 控制探索强度 | 想显式调节探索/利用权重时 |
标准 EI 的表达式是 EI(x) = E[max(0, f_best − f(x))],在高斯假设下展开成 (f_best − mu) * Φ(z) + sigma * φ(z),其中 z = (f_best − mu)/sigma,Φ 和 φ 分别是标准正态的分布函数和密度函数。第一项代表"能改进多少量",第二项代表"这里还有多大不确定度"。所以 EI 天然偏向两类点:预测均值低的(比现在最优更好)和方差大的(还没探过),这正是它能跳出局部最优的原因。
expected-improvement-plus 是工具箱默认值,它会在 EI 改进量长时间低于一个阈值时,给已经反复探索的区域加惩罚,强制把注意力转到没去过的地方。实践中我一般直接用默认,除非目标函数特别光滑、想加快收敛才换标准 EI。UCB 的 kappa 越大越偏向探索,越小越偏向利用,适合明确知道某个阶段该重点探索还是重点收敛的场景。
2.3 案例包的主循环:工具箱版和手写版各管什么
案例包里是两条路线。工具箱版一行调用,内部封装了 GP 拟合、核超参自动优化、采集函数最大化整个流程:
% 工具箱版主脚本骨架(example_toolbox.m) vars = [ optimizableVariable('x1', [-5, 5]); optimizableVariable('x2', [-5, 5]) ]; % 目标函数句柄:输入是 table,变量名与 optimizableVariable 一致 fun = @(x) myObjective(x); results = bayesopt(fun, vars, ... 'MaxObjectiveEvaluations', 30, ... 'AcquisitionFunctionName', 'expected-improvement-plus', ... 'IsObjectiveDeterministic', true, ... 'Verbose', 1);optimizableVariable 定义搜索空间,默认 type 是 real;如果参数只能取整数,改成 'Type','integer'。bayesopt 第一个参数是目标函数句柄,第二个是变量数组,后面的名值对是运行配置。MaxObjectiveEvaluations 控制最大评估次数,是预算的核心;AcquisitionFunctionName 换采集函数;Verbose 控制命令行输出。
手写版把这一行展开成三步:先初始化采样几个点,再用高斯过程拟合已有数据,最后最大化 EI 选下一个点。第 4 章会逐个函数拆开讲。工具箱版适合快速拿结果,手写版适合要加自定义逻辑的时候。我个人的习惯是先用工具箱版跑通建立基准,确认结果合理后再去改手写版,两个版本相互对照,出问题时能立刻定位是模型问题还是实现问题。
3. 用 bayesopt 调一个真实目标函数:从目标函数到结果解析的完整流程
这一章直接跑工具箱版。案例包里带了一个二维测试函数,刻意设置了多个局部极值,方便观察贝叶斯优化如何在后期把采样点集中在全局最优点附近。整个过程分三段:定义目标函数、跑优化、解析结果。
3.1 定义目标函数与优化变量:输入必须是 table
先记住 bayesopt 的一个硬规则:目标函数的入参不是数值向量,而是一个 MATLAB table,表的变量名列和 optimizableVariable 里定义的名字一一对应。第一次写的人经常在目标函数第一行就报"未定义变量",基本都是把 table 当成向量用了。
function obj = myObjective(x) % 输入 x 是 1 行 table,字段名对应优化变量的名字 x1 = x.x1; x2 = x.x2; % 多局部极值测试函数 obj = (x1 - 2).^2 + (x2 + 1).^2 - 5 * sin(x1 .* x2) + 1; end这里用 .^ 和 .* 而不是 ^ 和 *,是因为 bayesopt 内部可能以向量化方式同时评估多个点,写成标量运算符会报维度错误。目标函数里尽量不要依赖工作区全局变量,后面开并行评估时全局变量在所有 worker 里不一定同步。如果某个参数只能取整数,就在优化变量上加 Type:
vars = [ optimizableVariable('x1', [-5, 5]); optimizableVariable('x2', [-5, 5]); optimizableVariable('layers', [1, 10], 'Type', 'integer') ];integer 类型的变量在 GP 里仍然按连续变量做拟合,只在最后选点和评估时取整,所以不会漏掉整数候选。
3.2 运行 bayesopt 与结果解析:从 results 里挖出最优解
我手头是 matlab 2023b,bayesopt 的接口从 R2017a 起基本稳定,老版本直接跑这套代码也没问题。跑完返回一个 BayesoptResults 对象,最优参数、收敛历史、所有采样点都在里面:
% 运行贝叶斯优化,评估次数 30 rng(42); % 固定随机种子,保证可复现 results = bayesopt(@myObjective, vars, ... 'MaxObjectiveEvaluations', 30, ... 'AcquisitionFunctionName', 'expected-improvement-plus', ... 'IsObjectiveDeterministic', true); bestX = bestPoint(results); % 最优参数组合,返回 table minObj = results.MinObjective; % 历史最优目标值 trace = results.ObjectiveEvaluationTrace; % 收敛曲线数据 xAll = results.XTrace; % 全部评估点 objAll = results.ObjectiveTrace; % 每个评估点对应的目标值 figure; plot(results, 'all'); % 画出收敛曲线与评估点分布运行前固定 rng 是每次都会做的事,虽然工具箱内部有默认的随机源,但显式固定能让同一个脚本每次跑出的结果可复现。bestPoint 返回 table,直接用 bestX.x1 取具体值。ObjectiveEvaluationTrace 记录的是"截至第 k 次评估时出现过的最优值",画出来是一条不增的阶梯曲线。如果曲线最后一段还在明显下降,说明预算不足,应该加大 MaxObjectiveEvaluations 或者用 resume(results) 接着跑,不用从头再来。
XTrace 和 ObjectiveTrace 是一对一对齐的,可以用它们画散点图观察采样分布。后期采样点密集在最优区域、稀疏区域基本不再被访问,说明优化确实在"利用";如果采样点还是均匀撒在整个范围,多半是噪声开关没设对,回第 5 章排查。
3.3 关键参数配置:预算、采集函数、并行与确定性开关
这一节把最常用的配置项列成一张参数表,改之前先查表:
| 参数 | 取值示例 | 作用 |
|---|---|---|
| MaxObjectiveEvaluations | 30、100 | 最大评估次数,调参预算的核心控制项 |
| MaxTime | seconds(3600) | 最大运行时间,适合单次评估很贵的场景 |
| AcquisitionFunctionName | 'expected-improvement-plus' 等 | 采集函数策略 |
| IsObjectiveDeterministic | true / false | 目标函数是否确定性的关键开关 |
| UseParallel | true / false | 是否并行评估,需 Parallel Computing Toolbox |
| Verbose | 0 / 1 / 2 | 命令行输出详细程度 |
| PlotFcn | @plotMinObjective 等 | 实时画图回调 |
| XConstraintFcn | @constraintFun | 变量组合的合法性约束 |
其中 MaxObjectiveEvaluations 和 IsObjectiveDeterministic 对结果影响最大。前者决定预算,30 是能看出收敛趋势的最小值,测试函数成本低就直接给 100,收敛曲线会平滑很多;后者决定 GP 怎么理解观测噪声,凡是目标函数里有随机成分(交叉验证、蒙特卡洛、随机初始化),一律设 false,强制设 true 的后果在第 5 章有专门一节。
UseParallel 能显著缩短墙钟时间,但要注意:开了并行之后,目标函数里如果有随机数,复现会变得困难,需要额外做种子管理。单点评估耗时几秒以上才值得开并行,评估只要几毫秒的测试函数开了并行反而更慢。
注意:如果单次评估要几分钟,建议优先用 MaxTime 而不是 MaxObjectiveEvaluations。MaxObjectiveEvaluations 只数评估次数,不能保证在你可接受的墙钟时间内跑完;MaxTime 到点就停,返回当前最好结果。
4. 不依赖工具箱的手写贝叶斯优化:高斯过程与 EI 的 MATLAB 实现
工具箱版虽然方便,但如果你想改采集函数、做批量选点、或者加自定义约束,就得自己实现。这一章把案例包里手写版的核心代码拆开讲,全程只用到矩阵运算和 normcdf、normpdf,不需要任何额外工具箱。
4.1 协方差函数与高斯过程预测:把后验均值和方差算出来
高斯过程预测分两步:先算训练点之间的协方差矩阵 K,再算训练点和预测点之间的协方差 Kstar。案例包里用平方指数核,两个超参数:信号方差 sigma_f 和长度尺度 l。
function K = sekernel(X1, X2, sigma_f, l) % 平方指数协方差矩阵 % X1 是 n1xd,X2 是 n2xd,返回 n1xn2 n1 = size(X1, 1); n2 = size(X2, 1); K = zeros(n1, n2); for i = 1:n1 for j = 1:n2 d2 = sum((X1(i,:) - X2(j,:)).^2, 2); K(i,j) = sigma_f^2 * exp(-0.5 * d2 / l^2); end end end双层循环在点数不多时完全够用,几百个点以内都不需要向量化。sigma_f 控制函数值的整体幅度,l 控制相关长度——l 越小函数变化越剧烈,两个近距离的点也可能不相关;l 越大函数越平缓。对调参场景,l 的初始值决定了模型认为目标函数有多"陡"。
有了 K 和 Kstar,后验均值和方差按公式计算。数值上用 Cholesky 分解而不是直接求逆,因为直接 inv 在核矩阵条件数大时会翻车,Cholesky 稳定得多:
function [mu, s2] = gppredict(Xtrain, ytrain, Xtest, sigma_f, l, sigma_n) % 高斯过程后验预测,返回预测均值和预测方差 % sigma_n 是观测噪声标准差,确定性目标设为 1e-6 即可 N = size(Xtrain, 1); K = sekernel(Xtrain, Xtrain, sigma_f, l) + sigma_n^2 * eye(N); L = chol(K, 'lower'); % 下三角 Cholesky 分解 alpha = L' \ (L \ ytrain); % 先解下三角再解上三角 Kstar = sekernel(Xtrain, Xtest, sigma_f, l); mu = Kstar' * alpha; V = L \ Kstar; % 用三角方程避免显式求逆 s2 = sigma_f^2 - sum(V.^2, 1)' + sigma_n^2; end这段代码里,K 加了一个很小的噪声项保证正定;ytrain 是 n×1 列向量,L' \ (L \ ytrain) 是标准的 Cholesky 求解套路。输出的 mu 是 m×1 预测均值,s2 是 m×1 预测方差。方差在训练点附近会很小,在远离训练点的区域会接近 sigma_f^2——这正是贝叶斯优化需要的"不确定度地图"。
4.2 EI 采集函数与主循环:每一步选点和更新模型
采集函数在候选点上计算 EI 值,取最大者作为下一个实验点。候选点生成用最直接的方式:在变量范围内随机撒 1e4 个点,对它们算 EI 再取最大。低维问题里这个做法简单可靠,不需要写专门的优化器去最大化 EI。
function ei = ei_acq(x, Xtrain, ytrain, sigma_f, l, sigma_n, f_best) % 标准 EI 采集函数,输入 x 是 1xd 行向量 [mu, s2] = gppredict(Xtrain, ytrain, x, sigma_f, l, sigma_n); sigma = sqrt(s2); if sigma > 1e-12 z = (f_best - mu) / sigma; ei = (f_best - mu) * normcdf(z) + sigma * normpdf(z); else ei = 0; % 该点已被充分探索,方差为 0 end endz 衡量当前点离历史最优值差几个标准差,normcdf(z) 是改进概率,normpdf(z) 对应改进量的期望。sigma 特别小说明这个区域被探索得很充分,EI 直接返回 0,避免重复踩同一个点。
主循环把上述函数串起来:
% 手写贝叶斯优化主循环 rng(0); % 初始化:拉丁超立方采样 5 个点,映射到 [-5,5] Xtrain = lhsdesign(5, 2) * 10 - 5; ytrain = zeros(5, 1); for i = 1:5 xt = table(Xtrain(i,1), Xtrain(i,2), 'VariableNames', {'x1','x2'}); ytrain(i) = myObjective(xt); end f_best = min(ytrain); for iter = 1:25 % 在 1e4 个随机候选点上算 EI,取最大者 candidates = rand(1e4, 2) * 10 - 5; eiVals = zeros(1e4, 1); for i = 1:1e4 eiVals(i) = ei_acq(candidates(i,:), Xtrain, ytrain, 1, 1, 1e-6, f_best); end [~, idx] = max(eiVals); xNext = candidates(idx, :); % 评估新点并更新训练集 xt = table(xNext(1), xNext(2), 'VariableNames', {'x1','x2'}); yNext = myObjective(xt); Xtrain = [Xtrain; xNext]; ytrain = [ytrain; yNext]; f_best = min(ytrain); fprintf('iter %2d, x=[%5.2f %5.2f], y=%.4f\n', iter, xNext, yNext); end这段代码把 sigma_f 和 l 固定为 1,没有做边际似然优化。真实使用时长度尺度 l 应该每轮重新拟合,工具箱里 fitrgp 的自动优化干的就是这个事。如果目标函数的实际变化尺度和你给的初始值差距太大,GP 的方差估计会失真,EI 选点会偏。想快速提升效果,可以在每轮循环里用 fmincon 最大化对数边际似然来更新 l 和 sigma_f,多出来的代码不超过 30 行。
4.3 手写版与工具箱版的对比:精度差异与适用边界
手写版最大的价值是透明和可扩展。你能看到每一步在算什么,还能改出工具箱没有的策略,比如批量贝叶斯优化(每轮选多个点并行评估)、带约束的采集函数、自定义核函数。工具箱版胜在省心:GP 超参数自动优化、数值稳定性处理、并行、绘图全封装好了,正常调参场景没有理由不用它。
两者精度差别不大,主要差在 GP 超参数怎么设。工具箱版每轮会重新估计核函数参数,而这份手写版固定了超参数,从第 10 轮开始工具箱版通常收敛更快。把手写版的超参数优化补上之后,两者的收敛曲线基本重合。
案例包里两条路线都留了完整可运行脚本,建议先跑工具箱版建立"正常结果长这样"的基准,再跑手写版对照,任何一版出问题都能立刻定位是模型问题还是实现问题。
5. 实战避坑:贝叶斯优化最容易翻车的五个问题
跑通案例包只是第一步。下面五条是实际项目和帮同事排查时踩过的真坑,每条按"现象 → 原因 → 解决"的结构写,照着比对能省下半天查文档的时间。
5.1 目标函数返回 NaN,优化直接停摆
现象:bayesopt 跑到第几轮突然报错,提示 objective function 返回了 NaN 或 Inf;有时候不报错,但结果对象的 MinObjective 变成 NaN。
原因:目标函数在变量范围的边界区域没做合法性保护。比如参数取到负值时 log 报错、分母为 0、sqrt 负数,MATLAB 返回 NaN 而不是抛异常,bayesopt 把这个 NaN 当成合法观测喂给 GP,模型直接崩。
解决:目标函数入口统一做保护,非法输入返回一个大正数(比如 1e6)而不是 NaN,让优化器知道"这个地方很差";如果合法域是一个不等式区域,用 XConstraintFcn 写约束函数。案例包里 myObjective 开头加了 try-catch 兜底,改你自己目标函数时建议照抄这个结构。
5.2 最优解总贴在变量范围的边界上
现象:跑完 30 轮,bestPoint 恰好落在 x1 的下界或上界,而且附近的目标值比内部好一大截。
原因:范围给太宽,GP 在中间区域采样稀疏,EI 在边界处容易拿到高方差红利,于是反复往边界试探;另一种可能是真实最优本来就该落在更极端的值上,你给的边界把搜索空间限制偏了。
解决:先用 20 个随机点画散点图,看目标函数在范围内有没有明显的凹凸结构;对正数参数(学习率、惩罚系数这类)设 'Transform','log',让采样在对数空间均匀分布,避免数量级差异把 GP 的长度尺度带偏。如果贴边值确实好,把边界往那个方向再推一格重跑。
5.3 目标函数有噪声却声明确定性,模型过度自信
现象:同一个参数组合跑两次,目标值差 5%;优化结果每次重跑差异很大,后验方差在某些点接近于 0,收敛曲线看着漂亮但实际不可信。
原因:IsObjectiveDeterministic 设成了 true。工具箱认为观测无噪声,把随机波动当成真实函数变化去拟合,GP 过度自信,方差塌缩到 0,采集函数跟着乱选点。
解决:凡是交叉验证、蒙特卡洛仿真、带随机初始化的训练过程,一律设 false,让 GP 估计噪声项;如果噪声太大,先在目标函数里对同一个点重复 3 次取平均再返回,能明显改善收敛稳定性。案例包第 6 章的 SVM 例子用的就是 false,可以对照着看。
5.4 并行评估结果复现不出来
现象:用 UseParallel 跑出的最优解,固定了 rng 再重跑,结果还是不一样;记录里的采样点分布每次对不上。
原因:并行 worker 各有独立的随机数流,主进程的 rng 管不到 worker 里目标函数产生的随机性。只要目标函数内部用了 rand、randn、或者初始化神经网络,就会被并行池打乱。
解决:在目标函数内部用"按评估序号派生固定种子"的办法,每次评估前执行 rng(1000 + numEvaluated) 重新置位,保证同一个序号对应同一个样本流;复现实验时记录 MATLAB 版本、工具箱版本和并行池配置。实在要严格复现,就关并行跑一遍序列版。
5.5 维度一高就退化,贝叶斯优化也有边界
现象:20 维问题跑 100 轮,收敛曲线几乎是一条缓慢下降的直线,和随机搜索没区别。
原因:高维空间里 GP 拟合和 EI 选点的难度同时上升,采集函数在随机候选点上的最大值越来越没有区分度。这是贝叶斯优化的算法边界,不是代码 bug。
解决:先用随机森林或 fitrgp 的 ARD 参数做敏感度排序,把不敏感维度先固定;把维度压到 10 以内再上贝叶斯优化;或者接受现实,高维阶段用随机搜索探底,锁定一个小区域后切到贝叶斯优化细调。案例包里测试函数都是低维的,就是不想让新手一开始就撞上这个边界。
这五条里,NaN 和确定性开关是最容易踩的,前者直接崩,后者悄悄给你一个不可信的结果。我的排查顺序永远是:先查 NaN,再查确定性声明,最后才怀疑采集函数和维度问题。
6. 把案例包改造成你自己的调参工具:以 SVM 超参调优为例
最实用的改造是把 myObjective 换成交叉验证损失。以二分类 SVM 为例,优化变量是 BoxConstraint 和 KernelScale,目标函数返回 5 折交叉验证的错误率。这里有个关键操作:用匿名函数把训练数据 Xtr、ytr 带进目标函数,避免在目标函数内部访问工作区变量,这样开 UseParallel 时数据才会被正确分发给每个 worker。
vars = [ optimizableVariable('BoxConstraint', [1e-3, 1e3], 'Transform', 'log') optimizableVariable('KernelScale', [1e-3, 1e2], 'Transform', 'log')]; objfun = @(x) svmCVLoss(x.BoxConstraint, x.KernelScale, Xtr, ytr); rng(42); bo = bayesopt(objfun, vars, ... 'MaxObjectiveEvaluations', 40, ... 'AcquisitionFunctionName', 'expected-improvement-plus', ... 'IsObjectiveDeterministic', false, ... 'UseParallel', true); bestBox = bestPoint(bo).BoxConstraint; bestScale = bestPoint(bo).KernelScale;这里的 svmCVLoss 内部做 5 折交叉验证,返回错误率。两个变量都用 'Transform','log',因为 SVM 超参通常跨几个数量级,线性采样会把采样点全堆在小数值区。IsObjectiveDeterministic 设 false,交叉验证本身就是有噪声的评估。
验证步骤别跳过:把最优参数拿回去重新做一次完整的交叉验证,和优化过程中记录的最优值对比,差值大于几个百分点就说明噪声没控住,回到 5.3 检查确定性设置。如果目标函数便宜,在最优值附近做一次小范围网格搜索,看贝叶斯优化给出的是不是真的洼地,这一步能验证代理模型没骗你。
这套案例包在资源页可以直接拿,建议先把工具箱版跑通再去改手写版。我第一次拿这套流程调一个仿真模型的边界参数时,忘了处理 NaN,跑到第 12 轮模型就崩了;后来养成习惯,每次跑优化前强制走一遍:检查目标函数在边界处的合法性、确认确定性开关、固定种子、留一份收敛曲线存档。从那以后我再也没被贝叶斯优化的"玄学"坑过。希望帮到你。
本文还有配套的精品资源,点击获取