DACE工具箱实战:Kriging代理模型从原理到MATLAB实现
2026/8/31 15:29:53 网站建设 项目流程

简介:Matlab dace工具包是一套专用于构建克里金插值模型的开源算法库,面向具备基础Matlab编程能力的科研人员与工程技术人员,适用于空间建模、代理模型构建、实验设计优化等需要高精度响应面拟合的场景。资源压缩包共19个文件,含16个核心M函数(如dacefit.m、predictor.m、各类相关函数corrgauss.m/corrspherical.m等)、1个PDF使用说明书、1个MATLAB数据文件data1.mat及1个changelog更新日志,总大小仅1.48MB,轻量易部署。已有2650人学习下载,说明其在代理模型实践领域具有较高实用认可度。用户可直接调用dacefit进行模型训练,利用predictor快速预测,结合lhsamp或gridsamp生成采样点,并通过regpoly0/1/2选择不同回归项,配合详尽的dace.pdf文档,完整覆盖克里金建模全流程——从数据准备、超参选择、模型拟合到结果评估与可视化支持。 上周一个做结构优化的师弟跑来问我,说导师让他在项目里用DACE做代理模型,但他网上一搜发现这工具箱是二十多年前的产物,代码风格老派,文档还是PDF加网页混着来,心里直打鼓。我当时就跟他说:你导师没坑你,DACE确实是目前学术界和工业界里流传最广、最经典的Kriging代理模型工具箱之一,很多高水平论文里的代理优化结果就是用这玩意做出来的。你今天把它啃下来,往后看其它代理模型工具,基本就是降维打击。

DACE,全称Design and Analysis of Computer Experiments,最早由丹麦技术大学(DTU)的Hans Bruun Nielsen等人开发,专门用于计算机试验的设计与分析。它最核心的价值就一句话:用少量昂贵仿真样本,构造一个高精度的数学替代模型,然后用这个替代模型去做优化、灵敏度分析、参数标定,甚至嵌入到更大的数字孪生流程里。DACE这个名字本身就是一个设计哲学——它不是给你一堆通用函数库,而是把"实验设计"和"统计分析"串成一条流水线。

这篇文章我打算做一个完整的讲解,从数学骨架到代码实操,再到我这些年踩过的坑,覆盖dacefit训练、predictor预测、参数调优、模型评估,以及它和MATLAB自带fitrgp这类现代工具到底该怎么选。内容比较长,但每一步我都会给到可以直接复制的代码和解释,适合刚开始接触代理模型、或者已经在用DACE但一直"只会调用、不懂原理"的读者。

1. DACE是什么:一个二十年老工具箱为何还是硬通货

1.1 从名字说起:Design and Analysis of Computer Experiments

DACE这个缩写,拆开看是Design and Analysis of Computer Experiments,翻译过来就是"计算机试验的设计与分析"。这里的"计算机试验"指的不是传统物理实验,而是指那些跑一次要几个小时甚至几天的仿真程序——有限元分析、CFD计算、多体动力学仿真、电磁场模拟等等。这类仿真程序本质上是一个函数:给一组输入参数,算出一个或者多个输出指标。但问题在于,这个函数通常没有显式表达式,算一次成本极高,没法直接扔给优化器去暴力调用。

DACE的思路是:先在设计空间里选取少量样本点,跑仿真拿到对应的输出,然后用Kriging方法拟合一个统计代理模型。这个代理模型可以随时被调用,计算代价几乎为零,而且Kriging本身还会给出预测的不确定性估计。

DACE工具箱就是这套方法的一个经典实现。它的代码不花哨,没有花里胡哨的图形界面,但它把Kriging建模的核心步骤全部打通了:回归基函数、相关函数、超参数优化、预测和均方误差估计。这就是为什么直到今天,很多教科书、学术论文甚至工业软件内嵌的代理模型模块,底层逻辑都还是DACE这一套。

1.2 它到底解决了什么问题

我在项目里最常遇到的实际场景是这样的:手里有一个有限元模型,输入是材料参数和几何尺寸,输出是结构最大应力,跑一次要五分钟到半小时。这时候如果要做参数优化,用遗传算法直接跑,需要评估几千次,算下来几个月都不够用。但是用DACE,只需要先在参数空间里精心挑选几十个样本点,跑几十次仿真,训练一个Kriging代理模型,之后几千次评估都在代理模型上完成,可能几秒钟就出结果。最后再挑出最有潜力的少数几组参数,用真实仿真验证一下就行了。

更关键的是,DACE给的预测方差信息——这在贝叶斯优化里非常重要。它让你知道"哪里还没探明白",从而指导下一步该补样本点。这种"自带不确定性"的特性,是普通多项式响应面法(RSM)完全没有的。所以说DACE解决的核心问题是:计算成本与优化精度的矛盾

1.3 DACE与MATLAB自带fitrgp、surrogate toolbox的定位差异

很多新手会问:MATLAB的Statistics and Machine Learning Toolbox里不是有fitrgp吗?它也是高斯过程回归,为什么还要用DACE?这个问题我确实被问过很多次,我的理解是这样的:

fitrgp是通用机器学习工具,它面向的是带噪声数据的回归问题,所以默认情况下它假设观测值有噪声,会通过核函数和噪声方差来平滑数据。但DACE面向的是计算机试验,它假设仿真输出是确定性的——同一组输入,每次输出完全一样。因此DACE的训练过程会构造一个插值型Kriging模型,严格穿过所有样本点,不额外考虑观测噪声。这两种假设导致的结果是:用DACE拟合确定性的仿真数据,精度通常更高;用fitrgp拟合带噪声的物理实验数据,稳定性更好。

再说到MATLAB的Surrogate Model Toolbox(也就是现在的Response Optimization工具),它确实内置了Kriging、RBF等方法,用起来更省心,但对建模过程的可控性不如DACE。DACE的好处是透明的:相关函数怎么选、θ超参数怎么设、回归基函数用的什么,全都暴露给你。在写论文时、在复现算法时、在需要精细调参时,这种可控性是现代黑箱工具箱给不了的。

2. Kriging模型的核心骨架:回归项和相关函数怎么影响结果

2.1 别被公式吓到:Kriging就是在"全局趋势"上加"局部修正"

Kriging模型的数学形式可以写成:

y(x) = f(x)ᵀβ + z(x)

其中f(x)ᵀβ称为回归项,也可以理解成全局趋势项;z(x)是一个均值为零、协方差由相关函数决定的随机过程,用来捕捉局部偏差。很多人一看到公式就头疼,但用大白话解释非常容易:Kriging相当于先画一条"粗糙的宏观曲线",然后根据附近的样本点与目标点的距离关系,对这条曲线进行"精细的局部打磨"。

这个"距离关系"不是简单欧氏距离,而是由相关函数加上超参数θ控制的。DACE把回归项和相关函数设计成可以自由组合的模块,所以你在代码里看到的@regpoly0、@corrgauss这些句柄,本质上就是在指定你要用哪种宏观趋势、哪种局部打磨方式。

2.2 回归模型怎么选:regpoly0、regpoly1和regpoly2

DACE提供三类回归基函数:

  • regpoly0:常数回归,也就是假设全局趋势是某个未知常数。最常用,因为它把所有的形状细节都留给相关函数去刻画。
  • regpoly1:线性回归,假设趋势是输入的线性组合,适合响应有明显线性分量时使用。
  • regpoly2:二次回归,假设趋势是二次多项式,适合响应非常光滑且接近二次面的情况。

我个人的使用经验是:除非你有充足的先验知识,否则默认使用regpoly0就行。原因在于,相关函数本身已经足够灵活,可以拟合绝大多数非线性响应;引入高阶回归项反而会"抢走"相关函数的一部分解释能力,有时还会加大超参数辨识的难度。在DACE的官方文档示例里,大部分案例也是用regpoly0或者regpoly1。

2.3 相关函数怎么选:corrgauss、correxpent、corrspherical等

DACE内置了多个相关函数,它们的差异本质上是对"平滑程度"的假设不同:

相关函数数学形式(略去系数)特性与适用场景
corrgaussexp(-θ·d²)最常用,无限光滑,适合连续光滑响应面
correxpentexp(-θ·d)在原点处不光滑,适合响应面存在尖角或非光滑特征的情况
corrspherical分段函数,d超过阈值后相关为0局部相关,适合样本点间相关性衰减极快的场景
corrcubic三次样条形式介于光滑与非光滑之间
corrspline样条函数,平滑度可调数学性质好,但参数估计稍复杂

这里的d是样本点与预测点之间的某种距离,θ是需要优化的超参数。实际使用时,我最常用corrgauss,90%的光滑仿真输出都能用它得到不错的结果。但如果发现模型在训练点附近出现严重波动或虚假振荡,可以考虑换成correxpent试试。

需要注意,DACE中的corrgauss实际上还包含一个p参数(高斯指数),但在标准工具箱里p是固定为2的。如果你想用更灵活的指数p,需要自己扩展相关函数。在绝大多数应用里,p=2已经够用了。

2.4 θ参数的含义:相关性衰减速度与超参数优化

θ是相关函数里的超参数,它控制的是"相关性随距离衰减的速度"。θ越大,意味着两点之间的距离稍微拉开一点,相关性就立刻掉得很厉害,模型会变得"激进",更倾向于贴着样本点走;θ越小,相关性衰减越慢,模型越"平滑",抗局部波动能力越强。

DACE通过极大似然估计(MLE)来确定θ。简单说,就是找到一组θ,使得当前样本点下的似然函数值最大。这个过程不是闭式求解的,而是依赖数值优化,具体到DACE内部,它用的是逐维搜索的boxmin算法,这会在每个维度上通过fminbnd一类的一维优化器搜索最优值。这就是为什么θ的初始范围和上下界设置很重要,我们后面单独讲。

从物理意义上理解θ,还有一个非常直观的用法:训练完成后,比较不同维度的θ值大小,可以判断该输入变量对响应的影响程度和尺度。某个维度θ特别大,说明响应在这个方向上变化非常剧烈,敏感性很高;某个维度θ接近下界,说明这个输入可能几乎不影响输出。这种敏感性信息是DACE的副产品,很多项目里比预测本身还值钱。

3. dacefit训练实操:参数、返回值、代码模板

3.1 基本调用格式与输入参数拆解

dacefit的标准调用格式是:

[dmodel, perf] = dacefit(S, Y, regr, corr, theta0, lob, upb)

各参数含义如下:

  • S:样本点输入矩阵,大小为n×m,n是样本数,m是设计变量维度。
  • Y:响应值向量,大小为n×1。如果有多个输出,需要分别训练多个模型。
  • regr:回归模型函数句柄,例如@regpoly0、@regpoly1、@regpoly2。
  • corr:相关函数函数句柄,例如@corrgauss、@correxpent。
  • theta0:θ的初始值。可以是一个标量(所有维度相同),也可以是一个m×1向量。
  • lob:θ优化下界,标量或m×1向量。
  • upb:θ优化上界,标量或m×1向量。

这里特别容易踩的坑是theta0、lob、upb的设置。我把它们当成优化搜索空间来看:theta0是搜索起点,lob和upb是边界。如果边界给得太宽,优化器可能在某些维度上飘忽不定,收敛慢;如果给得太窄,可能把最优θ挡在边界外。下面给出我常用的启发式设置。

3.2 输出模型结构体里都有什么

dacefit返回的dmodel是一个结构体,里面存放了训练好的Kriging模型全部信息。最常用的字段包括:

字段含义
dmodel.regr回归模型的函数句柄
dmodel.corr相关模型的函数句柄
dmodel.theta优化后的θ值(m×1向量),反映各维度相关衰减速度
dmodel.beta回归系数向量
dmodel.gamma相关过程系数向量
dmodel.sigma2过程方差估计,反映整体拟合误差水平
dmodel.S训练样本输入矩阵
dmodel.Y训练样本响应向量
dmodel.lnL最大对数似然值,可用于模型比较

perf则是训练过程的性能记录,主要包含perf.niter(迭代次数)和perf.w(内部权重)等。平时我主要看niter判断优化器有没有正常收敛,如果niter特别少,要小心是不是一上来就碰到边界了。

3.3 一个可以直接改的通用训练模板

结合前面的参数讲解,我给出一个通用模板,可以直接复制到自己的脚本里改数据集:

% 数据准备 S = [...]; % n行m列,n个样本点 Y = [...]; % n行1列,对应响应 % 模型选择 regr = @regpoly0; corr = @corrgauss; % theta超参数设置 m = size(S, 2); theta0 = 1 * ones(m, 1); % 初始值 lob = 1e-4 * ones(m, 1); % 下界 upb = 100 * ones(m, 1); % 上界 % 训练 [dmodel, perf] = dacefit(S, Y, regr, corr, theta0, lob, upb); % 查看结果 dmodel.theta dmodel.sigma2 dmodel.lnL

这个模板里theta0我默认取1,这是个经验值。如果样本点的输入范围大致都在同一个量级(比如都归一化到0~1),theta0=1通常是个不错的起点。lob取下界1e-4,可以防止θ变成0导致矩阵奇异;upb取100,给优化器足够大的探索空间。

3.4 训练结果怎么看:perf输出与迭代信息

训练结果出来后,不要急着拿去预测,先检查几个地方:

第一,看dmodel.theta是不是明显落在边界上。如果一个维度的θ刚好等于lob或者upb,说明搜索边界设置得可能不合适,需要调整。第二,看dmodel.sigma2是否合理。sigma2是过程方差,它反映的是"用Kriging解释完趋势和相关后,还剩多少残差方差"。如果sigma2非常小(比如1e-10量级),通常是样本点之间太近,或者样本数量刚好让模型完美插值,这不一定是好事,可能意味着过拟合。第三,看lnL是否有明显异常。lnL是对数似然值,本身数值意义不是很大,但如果你用不同相关函数训练同一份数据,可以用lnL对比哪个模型更优(lnL更大者拟合更好)。

另外我建议把训练数据和模型预测值做一个散点图对比,肉眼检查模型是否穿过所有样本点。DACE是插值型Kriging,正常情况下预测值应该严格等于训练点的响应值。如果发现某几个训练点没穿过,说明训练过程出了问题,优先检查theta边界和矩阵条件数。

4. predictor预测与模型校验:从单点预测到全空间精度评价

4.1 predictor的基本用法与输出

训练好dmodel后,预测的核心函数是predictor,基本调用格式:

[yhat, or] = predictor(x, dmodel)

这里x可以是一个点,也可以是一批点组成的矩阵(每行一个点)。返回值:

  • yhat:预测值,行数与x相同。
  • or:可选输出,是一个结构体,包含预测相关的附加信息,最重要的是or.mse,即预测均方误差。

or里还有一些内部字段,比如or.sigma2、or.gamma等,用于推算预测方差。绝大多数时候,我们只需要用yhat和or.mse。

4.2 网格化预测与云图绘制

在我做过的项目里,最常规的操作就是在设计空间内画一张预测响应面的云图。代码如下:

% 假设模型输入为二维,范围分别为 [lb1, ub1], [lb2, ub2] x1 = linspace(lb1, ub1, 100); x2 = linspace(lb2, ub2, 100); [X1, X2] = meshgrid(x1, x2); Xpred = [X1(:), X2(:)]; [yhat, or] = predictor(Xpred, dmodel); Ypred = reshape(yhat, size(X1)); MSEpred = reshape(or.mse, size(X1)); % 绘制预测面 figure; surf(X1, X2, Ypred, 'EdgeColor', 'none'); hold on; plot3(S(:,1), S(:,2), Y, 'ko', 'MarkerSize', 6, 'MarkerFaceColor', 'r'); xlabel('x1'); ylabel('x2'); zlabel('y'); title('DACE Kriging代理模型预测面');

这段代码里有几个细节值得注意。一是预测网格的密度,100×100就是一万个预测点,predictor在DACE里是逐点计算的,如果样本量很大,网格预测会有点慢,所以不要一上来就搞500×500。二是样本点用黑色空心圈加红色实心标记画在响应面上,方便一眼看出模型是否穿过样本点。三是可以把or.mse也画出来,MSE大的区域就是模型"心里没底"的区域,这对后续加点采样非常有指导意义。

4.3 RMSE、R²与留一法交叉验证

预测画完图,必须做定量评估,否则不知道这个代理模型到底靠不靠谱。我常用的评估指标是RMSE和R²。如果你有额外的测试点(比如在验证集上评估),可以这样算:

% Ytrue_test 是测试点的真实响应,Yhat_test 是模型预测 RMSE = sqrt(mean((Yhat_test - Ytrue_test).^2)); SStot = sum((Ytrue_test - mean(Ytrue_test)).^2); SSres = sum((Ytrue_test - Yhat_test).^2); R2 = 1 - SSres / SStot;

RMSE反映绝对误差水平,R²反映模型能解释多少方差。R²大于0.95通常认为模型精度可以接受,大于0.99则非常好。

但很多时候我们没有额外的测试点——因为仿真太贵,样本点本来就不多。这时候就要用留一法交叉验证(LOOCV)。做法是:每次从n个样本点中留出一个点,用剩下的n-1个点训练模型,然后预测被留出的那个点,记录误差。循环n次后,统计平均误差。这个方法虽然要训练n次模型,但当n只有几十的时候非常实用。代码模板如下:

n = size(S, 1); e = zeros(n, 1); for i = 1:n idx_tr = true(n, 1); idx_tr(i) = false; dmodel_i = dacefit(S(idx_tr,:), Y(idx_tr,:), regr, corr, theta0, lob, upb); [yhat_i, ~] = predictor(S(i,:), dmodel_i); e(i) = yhat_i - Y(i); end cv_rmse = sqrt(mean(e.^2)); cv_R2 = 1 - sum(e.^2) / sum((Y - mean(Y)).^2);

LOOCV的好处是非常诚实——每个预测点都不在训练集里,能有效反映模型的泛化能力。我几乎在每一个DACE项目里都会跑一遍LOOCV,用它来指导样本量是否足够。

4.4 为什么or.mse只能当参考,不能当真理

predictor返回的or.mse,在Kriging理论里确实是对预测方差的一个估计,但在实际使用中,我很少把它当作绝对指标。原因在于它严重依赖于θ和相关函数的正确性,而θ本身是估计出来的,估计有偏差,MSE自然也就有偏差。尤其是当样本点很少(比如只有10个点建模5维问题)时,or.mse往往过于乐观,按它的"95%置信区间"来看,真实值甚至经常跑出区间外。

正确的使用姿势是:把or.mse当成一个相对指标,用于比较不同区域的"不确定度排名",而不是当成绝对误差上限。比如在贝叶斯优化里,我们用它作为EI(Expected Improvement)计算的一部分,选出"既有潜力又不够确定"的点去补样本,这种用法是稳健的。但如果你想用or.mse给客户打包票说"误差一定在多少以内",那我劝你换个方法。

5. 完整案例:给Branin函数建代理模型并做精度评估

5.1 问题定义与样本生成

前面讲了很多原理,这里用一个经典测试函数——Branin函数,把整个流程串一遍。Branin函数的表达式是:

f(x₁,x₂) = a(x₂ − b·x₁² + c·x₁ − r)² + s(1−t)cos(x₁) + s

其中a=1,b=5.1/(4π²),c=5/π,r=6,s=10,t=1/(8π)。定义域是x₁∈[−5,10],x₂∈[0,15]。这个函数有多个局部极小值点,形状非线性很强,非常适合用来测试代理模型。

我们先用拉丁超立方采样(LHS)生成30个样本点。MATLAB自带lhsdesign函数,可以直接用:

rng(42); n = 30; m = 2; lb = [-5, 0]; ub = [10, 15]; S_norm = lhsdesign(n, m); S = repmat(lb, n, 1) + S_norm .* repmat(ub - lb, n, 1); % Branin函数定义 a = 1; b = 5.1/(4*pi^2); c = 5/pi; r = 6; s = 10; t = 1/(8*pi); Y = a*(S(:,2) - b*S(:,1).^2 + c*S(:,1) - r).^2 + s*(1-t)*cos(S(:,1)) + s;

注意rng(42)的用意是让结果可复现。lhsdesign默认会给一个均匀性非常好的样本,但在实际工程中,你也可以根据自己的先验知识加权重——比如你知道某个区域响应变化剧烈,可以在这个区域多放点。

5.2 训练与预测的完整代码

接着训练模型,并在全空间网格上做预测:

regr = @regpoly1; corr = @corrgauss; theta0 = 1; lob = 1e-4; upb = 100; [dmodel, perf] = dacefit(S, Y, regr, corr, theta0, lob, upb); fprintf('theta: %f, %f\n', dmodel.theta(1), dmodel.theta(2)); fprintf('sigma2: %f\n', dmodel.sigma2); % 网格预测 x1g = linspace(-5, 10, 120); x2g = linspace(0, 15, 120); [X1g, X2g] = meshgrid(x1g, x2g); Xpred = [X1g(:), X2g(:)]; [yhat, or] = predictor(Xpred, dmodel); Yhat = reshape(yhat, size(X1g)); MSE = reshape(or.mse, size(X1g)); % 真实值用于对比 Ytrue_all = a*(X2g - b*X1g.^2 + c*X1g - r).^2 + s*(1-t)*cos(X1g) + s; RMSE = sqrt(mean((Yhat(:) - Ytrue_all(:)).^2)); R2 = 1 - sum((Yhat(:) - Ytrue_all(:)).^2) / sum((Ytrue_all(:) - mean(Ytrue_all(:))).^2); fprintf('网格评估 RMSE=%.4f, R2=%.4f\n', RMSE, R2);

在这个例子里,regpoly1配合corrgauss通常就能拿到R²接近0.99的结果。如果你用regpoly0,结果往往也差不多;但如果你错误地用correxpent,可能精度就会下降一些。所以不要小看相关函数的选择。

5.3 结果分析与参数敏感性

训练完成后,第一件事是看dmodel.theta。因为Branin函数在x₁方向上变化比x₂方向剧烈,正常情况下θ₁会比θ₂大不少。θ₁越大,说明x₁方向上相关性衰减越快,模型需要用更激进的变化去捕捉x₁方向的快速波动。如果你发现θ₁很小而θ₂很大,那就要警惕是不是样本设计出了问题,或者优化器没收敛。

其次是看dmodel.beta。当使用regpoly1时,beta就是线性趋势项的系数。对于Branin函数,这个系数不能直接和真实梯度的符号画等号,但它能反映一个粗略的方向性趋势。beta的绝对值大小也可以作为筛选重要变量的一个粗略参考。

再就是or.mse的分布。把MSE画成云图,你会看到高MSE区域通常集中在设计空间边缘,或者样本点稀疏的区域。这符合直觉——Kriging在"信息不足"的地方最心虚。如果后续要加点,优先往这些高MSE区域补样本。

5.4 把这个模型用进优化循环

模型的终极目标通常是优化。在代理模型上做全局优化的一个经典做法是:先在设计空间内用大量随机点或准随机点(比如Sobol序列)预测出响应值,挑出预测值最小的若干点,然后用真实仿真验证。如果验证结果不够好,就在预测最有潜力的区域附近补一个样本点,重新训练模型,迭代执行。这个过程通常叫"代理模型辅助优化"或"序列近似优化"。

我这里给一个非常简化的示例思路:

% 生成大量候选点 Ncand = 5000; Scand = repmat(lb, Ncand, 1) + rand(Ncand, m) .* repmat(ub - lb, Ncand, 1); % 代理模型预测 [yhat_c, or_c] = predictor(Scand, dmodel); % 按预测值排序 [~, idx] = sort(yhat_c); % 取预测最小的前10个点,算EI或者直接标记为候选 top10 = Scand(idx(1:10), :) ; % 对top10(或top1)跑真实仿真,验证 % Y_top10 = branin_func(top10); % 如果验证的最小值比当前已知最优还低,就把它加入训练集,重新训练。

这一步在工程里很常用。DACE的高效之处就在这里:一次训练完成后,可以零成本评估几千个候选点,从中筛选出少量值得跑真实仿真的点。相比直接用遗传算法跑仿真,这个流程通常能节省80%以上的仿真次数。

6. 常见报错与调参经验:矩阵奇异、优化失败与边界限制

6.1 'NaN'与奇异矩阵:样本太近的锅

DACE训练时最常见的报错,是计算过程中出现NaN,或者提示矩阵接近奇异(Matrix is singular)。这个问题的根源,绝大多数时候是样本点之间的相关性矩阵存在重复或接近重复的行。换句话说,样本点选得太近了,甚至有两个样本点完全重复。相关性矩阵一旦接近奇异,求逆就会失败,似然函数变成NaN,优化器直接崩掉。

解决办法很直接:检查样本点的重复性,去重;如果只是距离很近,那就重新做一次LHS,或者用聚类方法保证样本点之间的最小距离。另外一个经验是,lob不要设成0,设成1e-4这样的小正数,可以防止相关矩阵在对角线方向上出现数值退化。

6.2 theta0、lob、upb怎么给

关于θ的边界,我总结了一套自己的经验值:

  • 如果输入数据已经归一化到[0,1],theta0取1,lob取1e-3,upb取20,通常很稳。
  • 如果输入数据是原始物理量(比如一个变量是温度量级几百,另一个变量是尺度量级几毫米),那一定要小心。因为DACE的相关距离是直接对原始坐标算的,变量量级差异会让θ的搜索范围变得非常病态。我强烈建议先对S做归一化,再进DACE,预测时再反归一化。说白了,DACE对输入尺度极其敏感,归一化是几乎必须的预处理。
  • 如果训练后某个θ刚好卡在上界,把这个上界放大10倍再试;如果某个θ卡在下界,把它缩小10倍再试。这是最简单的边界诊断方法。

很多人喜欢把θ的上下界设成极宽(比如1e-10到1e10),觉得这样肯定不会错过最优。但实际效果往往不好,因为优化器在这种极端尺度下很容易数值失效。DACE内部用的是boxmin逐维搜索,每一步都需要在给定区间内做一维优化,区间太宽会让一维搜索的收敛精度下降。

6.3 DACE的适用边界:噪声数据、高维问题与现代工具箱对比

DACE虽然经典,但不是万能的。下面这几种情况,我建议你换工具:

第一,数据带噪声。如果你的响应值本身来自物理实验,或者仿真结果里有数值噪声(比如网格敏感性导致的小幅振荡),DACE的插值特性会让模型强行穿过所有点,结果就是响应面在噪声点附近出现不必要的波浪。这时更合适的选择是MATLAB的fitrgp(设定噪声方差)或者直接对数据做平滑预处理。

第二,高维问题。一般来说,样本量至少需要达到维度数的5到10倍,DACE的效果才好。如果维度在10维以上,而样本只有几十个,Kriging模型基本很难拟合出可靠响应面。这时可以考虑降维、变量筛选,或者换成稀疏回归模型。

第三,超大样本量。当样本量超过几千甚至上万时,DACE的预测速度会非常感人,因为每次predictor都要对全部样本点算相关性矩阵。如果你遇到这种规模,建议改用支持稀疏近似的现代高斯过程库。

对比起来,DACE的舒适区是:样本量几十到几百、维度2到8、输出确定性的计算机仿真数据。在这个区间里,它既轻量又透明,还能给你提供预测方差,性价比极高。

6.4 老代码迁移与工具箱安装的几个注意点

最后补充几个和安装、老代码迁移相关的细节。第一,DACE工具箱通常是从网上免费下载的,找MATLAB Central或者直接在搜索引擎里搜"DACE toolbox MATLAB"就能找到压缩包。不存在官方App安装器,下载后解压,把dace文件夹用addpath加进MATLAB路径即可。第二,DACE代码写得很早,在较新的MATLAB版本里运行时,偶尔会出现一些关于语法或类定义的警告,但绝大多数都不影响使用。第三,如果在使用中报错提示找不到dacefit,先检查路径是否添加成功,path里能看到dace目录才行。这是最最常见的"假报错"。

我还遇到过一个问题:有些老代码会用dmodel.theta这种圆点访问属性,但更老的版本里DACE返回的是一个class对象而不是struct,需要用get函数访问。如果你在旧资料里看到类似theta = get(dmodel, 'theta')的写法,而在新版本里运行报错,直接改成dmodel.theta即可。

做这套迁移的时候,我个人的建议是不要迷信老代码里所有的参数设置,有时候它们是为特定版本准备的。最稳妥的方式是用自带的demo脚本(dacefit.m底部通常有测试示例)跑一遍,确认环境没问题后,再替换成自己的数据。

我在实际项目中跑DACE有一个习惯:一定会把训练样本点和模型预测的对比图存下来,同时记录训练时间、θ值、sigma2、LOOCV的RMSE。这些信息在项目汇报和论文审稿时非常有用,因为审稿人经常问"你的代理模型精度多少",你总不能说"感觉还行"。如果你能给出完整的RMSE、R²、留一法误差,甚至画出预测误差分布图,这个模型的可靠性就有据可查了。

最后再分享一个小技巧:如果你发现同一个问题用不同的初始theta0训练,得到的θ差异很大,这说明似然函数有多个局部最优解。这时候不要只信一次训练的结果,可以多试几组theta0,保留lnL最大(或者说对验证集误差最小)的那组模型。这个小习惯帮我避免过好几次模型精度不稳定的尴尬情况。如果你也正在被代理模型的超参数选择困扰,不妨从这一项开始改进。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询