ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Matlab高斯过程回归实战:不确定性估计与核函数选择

Matlab高斯过程回归实战:不确定性估计与核函数选择 简介针对GPR高斯过程回归的Matlab实现资料面向需要利用概率模型进行回归预测与不确定性估计的科研与工程人员也适合机器学习初学者熟悉非参数方法。包体共8个文件包含Matlab脚本.m、RAR压缩包.rar和PDF教程三类整体约9.06MB既有可直接运行的gpr.m和Untitled.m完整示例也有配套的GPR Basics.pdf基础理论讲解以及多个压缩包内的扩展案例。该资源已有1469人浏览学习。内容从高斯过程的数学定义、常用RBF核函数、参数优化训练到后验分布预测与误差评估均有覆盖还包含变分推断和稀疏GPR等处理大规模数据的进阶主题可帮助读者掌握从基础理论到高效实现的全链路快速在Matlab中搭建并调优自己的高斯过程回归模型。1. 不确定性估计才是GPR的真正卖点做过试验数据拟合的人应该都有这种体会用BP网络或者随机森林去拟合一条带噪声的响应曲线模型训练完只能拿到一个点预测现场工程师问这个位置预测值波动多大你答不上来。高斯过程回归GPR不一样它在给出均值预测的同时每个点上还会输出一个方差估计直接告诉你模型在这个位置有多确定。这个特性在设备标定、试验数据补偿、替代模型构建场景里非常实用数据量不需要大几十个样本就能得到合理的结果。这也是该资源里的gpr.m和Untitled.m存在的意义——它们把从核函数定义、超参数训练到预测区间画图的完整流程写成了可以跑通的Matlab代码省去了从理论推导到工程实现的中间成本。2. 核函数与先验GPR里真正决定预测质量的部分2.1 高斯过程的数学定义与Matlab中的表示高斯过程是一族随机函数的集合任意有限个输入点上的函数值服从联合高斯分布。一个GP完全由均值函数 m(x) 和协方差函数 k(x, x) 确定后者就是我们常说的核函数。GPR在训练阶段做的事情就是基于观测数据去推断这个函数分布的后验形式。Matlab中建模GP核心步骤是把核函数写成函数句柄。以最常用的平方指数核为例% 定义RBF核函数返回n1 x n2协方差矩阵 kRBF (x1, x2, sigma, l) ... sigma^2 * exp(-0.5 * (pdist2(x1, x2).^2) / l^2);这段代码里pdist2是Matlab自带函数直接计算两个输入矩阵之间的两两欧氏距离比手写双重for循环快一个数量级。sigma控制函数值的整体幅度l是长度尺度决定函数随着输入距离增加而变化的快慢程度。l越小函数越曲折能拟合更剧烈的波动l越大函数越平滑。写核函数时有一个容易被忽略的性能问题超参数优化过程会反复调用核函数如果训练集有几百个点每次调用都是一个几百乘几百的协方差矩阵运算。因此核函数内部必须向量化避免循环。上面这个写法可以做到万次级别调用不卡顿。2.2 常见核函数对比与选型不同的核函数编码了不同的先验假设选型对预测质量的影响几乎是决定性的。下面这个表是实际项目中常用的对比核函数数学形式Matlab实现要点适用场景平方指数/RBFσ² exp(-r²/2l²)pdist2后平方平滑性最强底层函数光滑连续无突变Matérn 3/2σ²(1√3r/l)exp(-√3r/l)对距离开根号后再算函数有不可导点或噪声较大Matérn 5/2σ²(1√5r/l5r²/3l²)exp(-√5r/l)同上可导性高一阶一阶可导但二阶不稳定的数据有理二次核RQσ²(1r²/(2αl²))^(-α)注意α较大时数值稳定性数据呈现多尺度特征选核第一条原则RBF是默认起点但它假设底层函数无穷阶可导这在物理测量数据里往往过强。当预测曲线在训练点附近出现不自然的弯曲时换Matérn 3/2通常能改善。第二条原则输入维度大于3时单一长度尺度会让各个维度的变化被平均化此时建议改成各向异性形式例如kAniso (x1, x2, sigma, l) ... sigma^2 * exp(-0.5 * sum((pdist2(x1, x2)./l).^2, 2));这里的l是行向量每个维度一个长度尺度。各向异性核在高维输入下比单一长度尺度的效果提升明显代价是超参数数量从2个变成d1个优化时间会相应增加。2.3 为什么均值函数通常设为零GPR的标准设定是零均值函数 z ~ GP(0, k)理由是核函数本身已经提供了足够的建模能力均值函数非零只会让参数估计变得更复杂。理论推导中后验均值可以写成核矩阵与观测值的线性组合零均值假设下这个公式最简洁。但是在工程实现中零均值的假设要求数据满足一个隐含前提输出y的分布大致以0为中心。如果你的试验数据是几百上千的量级直接喂进去训练核函数的 σ² 会被拉到很大的值计算过程中容易出现数值过大的问题。常见的处理方式是先标准化yMean mean(y); yStd std(y); yStd max(yStd, 1e-6); yNorm (y - yMean) / yStd;对输入X也做标准化让每个维度的范围压缩到[-2,2]左右。标准化的意义不只是数值稳定更重要的是让长度尺度参数有一个可预期的参考范围。标准化之后l从1附近初始化就是合理的如果X原始量纲是毫米、度、伏特混在一起l作为单个数根本无法同时适配所有维度。注意不要跳过标准化这一步。未经标准化的GPR长度尺度会被量纲最大的维度主导训练出的超参数在物理意义上很难解释预测区间也会明显偏移。3. gpr.m训练全流程从数据准备到预测区间3.1 主线与数据准备Untitled.m这类脚本把GPR的落地分成了四段准备数据、定义核函数、优化超参数、预测画图。gpr.m实现的就是后两段的核心逻辑。在我们自己的流程里先约定输入形式X是 n×d 的输入矩阵y是 n×1 的输出向量n为样本量d为输入维度。数据准备阶段有三个细节值得注意。第一检查X中是否有重复点重复输入会导致核矩阵出现完全相关的行列Cholesky分解直接报错第二对y做异常值剔除GPR对离群点相当敏感一个偏离群体过大的点会把附近区域的后验均值拉偏第三如果d大于5建议先做PCA降维GPR的样本复杂度随维度增长很快冗余维度会让长度尺度参数优化不稳定降到2~3个主成分后训练速度和预测区间质量都会有可感知的改善。3.2 gpr.m的核心负边际似然与梯度优化GPR的训练目标不是最小化训练误差而是最大化边际似然——即在这些超参数下观测数据出现的概率。实操中更适合用负对数形式方便做无约束优化。下面是一个可直接运行的gpr.m实现function [model, fit] gpr(X, y, theta0) % GPR训练学习核超参数并保存分解结果 % 输入: X 训练输入(nxd), y 训练输出(nx1) % theta0 超参数初值 [log(sigma), log(l)] % 输出: model 包含协方差分解结果的结构体 % fit 优化收敛信息 y (y - mean(y)) / std(y); % 标准化 n size(X, 1); % 负边际对数似然函数theta取log形式保证sigma和l恒为正 nll (theta) gpNegLogLik(theta, X, y, kRBF); options optimoptions(fminunc, ... Algorithm, quasi-newton, ... Display, iter, ... MaxIterations, 500); bestNll inf; for trial 1:5 th0 theta0 0.1 * randn(size(theta0)); [thOpt, nllVal] fminunc(nll, th0, options); if nllVal bestNll bestNll nllVal; thetaBest thOpt; end end sigma exp(thetaBest(1)); l exp(thetaBest(2)); K kRBF(X, X, sigma, l); K K 1e-6 * eye(n); % jitter防止数值病态 L chol(K, lower); alpha L \ (L \ y); model.L L; model.alpha alpha; model.X X; model.y y; model.sigma sigma; model.l l; fit.nll bestNll; end对应的负对数似然函数function nll gpNegLogLik(theta, X, y, kernel) sigma exp(theta(1)); l exp(theta(2)); K kernel(X, X, sigma, l) 1e-6 * eye(size(X,1)); L chol(K, lower); alpha L \ (L \ y); nll 0.5 * y * alpha sum(log(diag(L))) 0.5 * size(X,1) * log(2*pi); end代码里把theta取了对数形式目的是让 σ 和 l 在优化过程中自动保持正值不需要额外加约束。fminunc的 quasi-newton 算法对于这种不超过10个参数的问题足够稳定不需要手写梯度。如果Unexpectedly出现收敛失败注意看迭代过程中nll是否有下降趋势没有的话可能是初值离最优解太远或者数据本身有异常。K K 1e-6 * eye(n)这一行是很多入门代码里没有的。不加 jitter 时核矩阵在样本点密集或噪声极小时可能条件数过大chol分解会报 Matrix must be positive definite 错误。jitter 加得太大又会污染预测方差1e-6 是经验折中值。3.3 Untitled.m里的预测与画图训练完成后预测的核心是计算新点与训练点之间的协方差然后基于联合高斯分布的条件分布公式得到均值和方差。这个步骤在Untitled.m里表现为一个完整的预测函数加绘图代码function [mu, s] gpPredict(model, Xstar) % 模型预测返回均值与标准差 % model: gpr.m训练结果, Xstar: 预测点(mxd) Kstar kRBF(model.X, Xstar, model.sigma, model.l); v model.L \ Kstar; mu Kstar * model.alpha; % 方差 先验方差 - vvv由Cholesky分解得到 Kss kRBF(Xstar, Xstar, model.sigma, model.l); s2 diag(Kss) - sum(v.^2, 1); s sqrt(max(s2, 0)); % 数值保护避免微小负值 end% 主脚本拟合与绘图 [X, y] loadSampleData(); % 实际使用时替换为你的数据 theta0 [log(1), log(1)]; % sigma1, l1 初始化 [model, ~] gpr(X, y, theta0); xgrid linspace(min(X)-0.5, max(X)0.5, 200); [mu, s] gpPredict(model, xgrid); figure; fill([xgrid; flipud(xgrid)], ... [mu1.96*s; flipud(mu-1.96*s)], ... [0.8 0.9 1], EdgeColor, none); hold on; plot(X, y, ko, MarkerSize, 6); plot(xgrid, mu, b-, LineWidth, 1.5); xlabel(x); ylabel(y);fill命令先画置信带再用plot叠加散点和均值曲线是Matlab里画置信区间的标准组合。1.96 对应95%置信水平如果业务场景要求90%或99%换成1.645或2.576即可。预测方差在训练点附近应该接近噪声方差远离训练数据的地方则逐渐增大这两个趋势同时出现说明模型训练是健康的。如果远离数据点时置信带没有扩开多半是长度尺度被优化得过大模型误以为函数处处平滑。4. 超参数敏感性初始化、噪声方差与收敛陷阱4.1 超参数初始化策略GPR的负边际似然函数不是凸函数存在多个局部极小值初始化不对直接决定最终预测质量。工作经验总结下来按照下面这个表的策略做初始化和约束绝大多数数据集都能得到满意结果超参数常见错误做法推荐做法原因信号方差 σ²取0.1这样的任意小值取标准化后y方差的一半保证先验信号量级和数据匹配长度尺度 l从标准正态采样输入标准化后用1附近标准化后x范围可预期l1合理噪声方差 σ_n设为0设为y标准差的1%并设下界零噪声导致病态矩阵和过拟合起点数量只跑1次5~10个随机扰动起点避开局部极小值超参数初始化的核心逻辑是在标准化数据上σ 的量级应当与输出信号匹配l 的量级应当与输入范围匹配。先跑一次快速预训练拿到粗略的参数范围再在这个范围附近做多起点精细化比直接盲试效率高很多。4.2 多起点与梯度校验上一章代码里已经用了5个随机起点的策略。这里解释一下背后的原因fminunc从不同初值出发最终收敛到的局部极小值可能完全不同负对数似然相差10以上都不稀奇。多起点里的每次扰动幅度0.1 * randn是刻意控制的小步扰动在实际运行中一个起点落在错误波谷时其他起点能补救回来的概率相当高。梯度校验是一个容易被忽视的步骤。手动实现负对数似然时求导公式任何一个小错误都会让优化走向错误方向。标准做法是用有限差分验证数值梯度% 数值梯度校验对每个theta分量做中心差分 eps0 1e-6; gradNum zeros(size(theta0)); for i 1:length(theta0) thP theta0; thP(i) thP(i) eps0; thM theta0; thM(i) thM(i) - eps0; gradNum(i) (nll(thP) - nll(thM)) / (2 * eps0); end如果数值梯度和解析梯度的相对误差超过1e-4需要检查公式是否存在符号或索引错误。fminunc默认使用BFGS拟牛顿法其实对梯度精度要求不高但梯度方向错了它会直接报错或者收敛到异常点。4.3 噪声方差过低时的过拟合表现噪声方差σ_n²是GPR里唯一直接控制模型多信任数据的参数。它太小的时候模型会把训练点的噪声也当作真实信号来拟合表现出的症状非常典型后验均值曲线呈现锯齿状每个训练点都被精确穿过预测方差在训练点附近几乎为0远离点迅速膨胀测试集上误差反而增大。诊断这个问题的办法很简单。第一画出预测曲线肉眼看是否平滑第二查看训练得到的σ_n值是否被压到了下界附近。实践中建议在参数化时就给噪声设一个下界避免优化器把它推向0sigma_n exp(theta(3)) 1e-4;把待优化参数从噪声标准差改为噪声标准差的对数加常数下界这样无论theta(3)优化到什么值σ_n 都不会低于1e-4。这个技巧在样本量小、数据相对干净的工业数据上特别重要因为真实试验数据不可能没有噪声强行拟合反而破坏了模型的泛化能力。5. SGP与大数据量稀疏高斯过程的落地技巧5.1 训练复杂度与临界点GPR训练的主要计算量集中在核矩阵的Cholesky分解上复杂度是O(n³)n是训练样本数。n500时单次分解大约几十毫秒n2000时已经到秒级n10000时单次迭代就是分钟级——这还不算超参数优化需要的几十次迭代。实际项目中样本量超过2000就开始需要考虑近似方法超过10000基本只能用稀疏近似或随机特征近似。资源里的SGP.rar就是围绕这个场景展开的。5.2 稀疏GPR的核心思路与实现方向稀疏GPR的基本思想是引入 m 个诱导点用这m个点上的函数值代替全部n个训练点来近似后验把复杂度从O(n³)降到O(nm²)。m通常取50~200远小于n时计算量大幅下降预测精度损失在可接受范围内。诱导点的选择是关键常见做法有K均值聚类中心、均匀网格、随机采样三种其中K均值聚类中心在输入分布不均匀时效果最好。Matlab自带的fitrgp也提供了稀疏近似选项设置KernelFunction,squaredexponential和PredictMethod,sd即可启用但底层的诱导点选择算法不可控。自己实现时诱导点应该集中在数据密度高的区域如果均匀分布在输入空间里数据稀疏的地方诱导点过多数据密集的地方反而不够用。5.3 用不确定性做主动采样GPR的预测方差不仅是一个统计量还可以直接作为下一轮实验的采样依据。做法是定义一个采集函数通常是均值加一个不确定性项然后在候选点上最大化这个值% 主动采样选择不确定性最大的区域补充实验点 candidateX linspace(min(X), max(X), 1000); [mu, s] gpPredict(model, candidateX); beta 2.0; acq mu beta * s; % UCB采集函数 [xNext, idx] max(acq); % 下一轮实验点 nextSample candidateX(idx);这里的beta控制探索和利用的平衡。beta0是纯利用只选预测均值最大的点beta2左右在探索和利用之间相对均衡试验成本低的场景可以加大beta到3以上。主动采样特别适合代价高昂的物理试验——比如高温炉标定、风洞实验每补一个点都要花大成本用GPR的不确定性引导采样比均匀布点或用梯度下降找极值点能节省约一半的试验次数。候选点网格的密度在这里很关键太稀疏会漏掉真正的极值区域太密又浪费计算一般1000~2000个候选点足够。本文还有配套的精品资源点击获取
返回列表