ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于相关向量机的多输入多输出回归:稀疏建模与置信区间预测

基于相关向量机的多输入多输出回归:稀疏建模与置信区间预测 简介该代码包基于相关向量机RVM的多输入多输出回归分析MATLAB实现面向本科及以上科研、工程或课程设计人群解决多变量输入与多目标输出间的回归建模问题。代码包含完整主程序与RBF核函数实现配套Excel示例数据关键算法位置附有注释便于快速掌握RVM原理并替换为自己的数据实现预测、仿真或算法对比。资源共4个文件以2个m脚本、1个xlsx数据文件和1个asv自动备份文件为主压缩包仅153KB文件构成清晰下载后可直接导入MATLAB运行。目前已有88人学习使用适合需要快速验证相关向量机回归效果的读者。通过该资源可省去从零搭建RVM框架的时间直接获得可运行的多输入多输出回归方案同时可结合自身任务调整输入输出维度或核参数或联系博主进行创新修改满足工业建模、经济预测等扩展应用需求。1. 多输入多输出回归里缺的不是模型是稀疏性和置信度做回归分析的人迟早会碰到这样一件事输入变量十几个输出指标三五个用线性回归结果太弱换成神经网络又说不出每个变量到底起了什么作用预测值还没有可靠度。基于相关向量机的多输入多输出回归分析解决的就是这个位置的需求。RVM相关向量机是一种稀疏贝叶斯回归方法训练完大部分权重自动收缩成零只留下少数“相关向量”同时每个预测自带方差多输入多输出场景下就变成一套数据同时预测多个目标并各自给出置信区间。它特别适合训练样本不太多、特征维度不低、又希望结果能解释的回归任务比如电池SOC多指标估计、工业过程质量预测、量化交易里的多标的多因子映射。下面这套方案把建模、实现、调参和踩坑一次说透。2. 相关向量机凭什么在回归里给“置信度”先看懂它在算什么事2.1 相关向量不是“支持向量换个名字”权重的先验是怎么剪枝的先把RVM的核心逻辑说清楚因为后面所有参数调整都建立在这一节上。SVM回归站在几何角度找一个 epsilon 不敏感带只保留落在带边界上的支持向量。RVM站在贝叶斯角度每个训练样本对应一个基函数权重 w 的先验是均值为 0、方差为 1/alpha_i 的高斯分布然后通过数据迭代去更新这些 alpha_i。关键在更新规则。设核矩阵为 Phi训练输出为 y噪声精度方差倒数为 beta权重后验分布的协方差和均值分别是Sigma inv(beta * (Phi * Phi) diag(alpha)); mu beta * Sigma * Phi * y;然后计算 gamma_i 1 - alpha_i * Sigma_ii它衡量第 i 个基函数被数据“支持”的程度。alpha_i 的更新公式是 gamma_i / mu_i^2。注意看这个公式如果第 i 个权重 mu_i 很小alpha_i 就会变得很大而 alpha 是权重方差的倒数alpha 趋向无穷大等价于这个权重被压成 0。于是迭代过程中大量基函数的 alpha 会超过一个剪枝阈值常用 1e8这些列就直接从核矩阵里删掉。剩下的样本就是相关向量。这个过程不需要你人为指定稀疏度它是被数据推出来的。同时 beta 也参与迭代更新公式是 (N - sum(gamma)) / ||y - Phi*mu||^2噪声方差也能估计出来。所以 RVM 天然能做两件 SVM 做不到的事自动确定模型的复杂度以及给出每个预测点的方差。正是这个方差构成了多输出场景下区间预测的基础。2.2 多输入多输出回归的两种建模路径独立模型与共享结构多输入多输出回归MIMO在 RVM 框架下有两种走法。第一种最简单拆成 Q 个单输出模型输出有几个就独立训练几个 RVM。每个输出有自己的 alpha、自己的相关向量集合、自己的噪声方差互不干扰。第二种是共享结构所有输出用同一个核矩阵和同一套 alpha 做联合推断试图把输出之间的相关性也建模进去。我一般默认走独立模型理由很实际。工业过程里的多输出往往是不同量纲的指标比如一个输出是温度、一个输出是浓度它们的噪声水平、非线性程度都不一样强行共享一套 alpha 容易让强输出带偏弱输出。独立模型每个输出自己选自己的相关向量相当于每路回归都自动做了特征选择从结果上看就是“每个目标依赖的输入基函数不同”。共享结构的收益主要出现在输出之间强相关且噪声相近的任务里代价是求解复杂不少而且多任务版 RVM 的收敛大概率比单输出更难调。先把独立模型跑稳再考虑共享这是最不容易翻车的路径。2.3 RVM、SVM、BP 和弹性网络的取舍一份对比表选型这事不能只看精度要看场景给什么约束。下面这份对比表可以作为方案评估时的参照模型预测是否带方差稀疏性需要调的参数小样本表现多输出支持RVM带很稀疏核宽、剪枝阈值、迭代容差好独立建模天然支持SVM 回归不带较稀疏C、epsilon、核宽一般需要包装BP/MLP不带不稀疏层数、神经元、学习率等一堆容易过拟合输出层可多节点弹性网络ElasticNet不带线性稀疏L1/L2 比例、正则强度视线性程度需要循环RVM 最大的差异化在于两点一是预测带方差后面可以拿来做区间预测和异常检测二是相关向量数量通常远少于支持向量数量模型落盘和在线推理都轻。它的短板也明显训练涉及对 N 阶矩阵求逆样本到几千时计算量会很难受高斯核宽度一旦设得不好性能波动比 SVM 还明显。所以它适合中小样本、中低维度、重视可解释性和置信度的回归任务。如果你的数据量到了十万级或者场景只关心点预测精度那就直接考虑梯度提升或深度模型不要在 RVM 上硬耗。3. 用 MATLAB 把 RVM 多输出回归跑起来三个可直接复现的代码块这一章给一套能直接落地的最小实现。我从数据组织、单输出 RVM 求解、多输出组装与评估三个环节各给一段示例代码整体思路是标题里说的“数据齐全”落到实际操作上就是一张多输入多输出的表格省去你自己构造数据的步骤下面代码按这份流程替换成你自己的数据即可。3.1 数据怎么摆输入输出结构、划分和标准化多输入多输出的数据在表格里的摆法很统一每一行是一个样本前 D 列是输入特征后 Q 列是输出目标。比如一份电池测试数据电压、电流、温度、循环次数是输入容量和内阻是输出那就是“8 输入 2 输出”。读取、划分、标准化的代码按下面来%% 1. 数据读取、划分、标准化 % 假设 data.xlsx 前 8 列为输入特征后 3 列为输出目标 data readmatrix(data.xlsx); X data(:, 1:8); % 输入n x 8 Y data(:, 9:11); % 输出n x 3 N size(X, 1); rng(2024); % 固定随机种子保证可复现 idx randperm(N); tr_idx idx(1:round(N*0.7)); % 70% 训练 te_idx idx(round(N*0.7)1:end); % 30% 测试 % z-score 标准化均值和方差从训练集估计再应用到测试集 [Xtr, mu_x, sig_x] zscore(X(tr_idx, :)); Xte (X(te_idx, :) - mu_x) ./ sig_x; [Ytr, mu_y, sig_y] zscore(Y(tr_idx, :)); Yte (Y(te_idx, :) - mu_y) ./ sig_y;这段代码里的关键点有两个。第一标准化必须在训练集上估计均值和方差然后把同一组 mu_x、sig_x 套到测试集上而不是对测试集单独做 zscore否则测试分布被泄露进流程回归分析结果会虚高。第二输出也要标准化。多输出的量纲经常差一个数量级比如一个输出在 0.1 量级、另一个在 100 量级不标准化的话小量纲那个输出基本不会被模型在意后面评估时还会被大量纲输出主导。3.2 RVM 核心求解alpha 迭代、剪枝与噪声估计示例代码讲解RVM 的很多开源实现包了一层花哨的界面核心做事的其实是下面这段迭代。理解了这段再去看任何封装好的代码你都不会被黑匣子吓住%% 2. RVM 单输出回归核心求解器 function [mu_w, alpha, beta, Sigma, rv_idx, y_pred, var_pred] rvm_fit(Xtr, ytr, Xte, kfun, kpar, opts) prune_th 1e8; % alpha 剪枝阈值 max_iter 200; % 最大迭代轮数 tol 1e-3; % 收敛判定容差 Phi kfun(Xtr, Xtr, kpar); % 初始基函数矩阵n x n idx_all (1:size(Phi,2)); N size(Phi, 1); alpha ones(size(Phi,2), 1); % 权重精度初值 beta 1 / (var(ytr) eps); % 噪声精度初值 for iter 1:max_iter Sigma inv(beta * (Phi*Phi) diag(alpha)); mu_w beta * Sigma * Phi * ytr; gamma 1 - alpha .* diag(Sigma); alpha_new gamma ./ max(mu_w.^2, eps); % 更新每个权重精度 err ytr - Phi * mu_w; beta_new (N - sum(gamma)) / (err * err); % 更新噪声精度 % 收敛判断alpha 和 beta 变化都小于容差就停 if iter 5 da max(abs(alpha_new - alpha) ./ max(alpha, eps)); db abs(beta_new - beta) / abs(beta); if da tol db tol, break; end end alpha alpha_new; beta beta_new; % 剪枝alpha 过大的基函数对应权重被压成 0直接从矩阵删列 keep alpha prune_th; Phi Phi(:, keep); idx_all idx_all(keep); alpha alpha(keep); if isempty(alpha) error(所有基函数都被剪掉请调整 beta 初值或核宽度); end end % 用保留下的相关向量重新计算最终后验 Sigma inv(beta * (Phi*Phi) diag(alpha)); mu_w beta * Sigma * Phi * ytr; rv_idx idx_all; % 相关向量在原始样本里的位置 % 测试集预测均值加逐点方差 Phite kfun(Xte, Xtr(rv_idx, :), kpar); y_pred Phite * mu_w; var_pred 1/beta sum((Phite * Sigma) .* Phite, 2); end代码逻辑拆开看是四步循环算后验、更新 alpha 和 beta、判断收敛、剪掉无用基函数。alpha 更新公式里 mu_w^2 用的是 max(mu_w.^2, eps)是防止 mu 为 0 时除零剪枝阈值 prune_th 设 1e8 表示 alpha 超过 1e8 就认为这个权重已经没有存在价值。这里有一个容易忽略的细节剪枝后继续迭代时alpha 向量的长度跟着变短收敛判断里的 alpha_new 和 alpha 长度仍然一致因为 alpha_new 是剪枝前算的、alpha 是剪枝后更新的两者长度一致才比较如果剪枝发生在收敛判断之前长度就会对不上这也是很多自写实现报维度错误的原因。预测方差 var_pred 分两部分第一项 1/beta 是噪声方差第二项是权重不确定性通过核函数传播到预测点的方差。这两项缺一不可后面避坑章节会专门讲漏掉第二项的后果。配套的高斯核函数如下我习惯把核做独立函数方便在 RBF 和多项式核之间切换%% 2.1 高斯核函数 function K build_kernel(A, B, width) % A、B 都是样本矩阵行是样本 d2 pdist2(A, B, squaredeuclidean); % 两两平方距离 K exp(-d2 / (2 * width^2)); end这里 width 是核宽度也就是高斯函数的尺度参数。它决定了基函数的作用范围宽度越小基函数越尖模型越容易拟合噪声宽度越大基函数越平所有样本之间的相似度都趋近 1核矩阵容易病态。这个参数基本是 RVM 里最敏感的一个旋钮第五章会专门讲怎么系统地去选它而不是拍脑袋。3.3 多输出怎么组装训练、预测和区间覆盖率的评估多输出在 RVM 框架下最常见的做法就是把 3 个输出看成 3 个独立回归任务。组装代码%% 3. 多输出每个输出独立训练一个 RVM Q size(Ytr, 2); model cell(Q, 1); Yp_te zeros(size(Yte)); Vp_te zeros(size(Yte)); for q 1:Q model{q} rvm_fit(Xtr, Ytr(:,q), Xte, build_kernel, 0.8, []); % 核宽 0.8 Yp_te(:,q) model{q}.y_pred; Vp_te(:,q) model{q}.var_pred; end % 还原到原始尺度预测均值还原用 mu_y/sig_y预测方差还原要乘 sig_y^2 Yp_te_ori Yp_te .* sig_y mu_y; Vp_te_ori Vp_te .* (sig_y.^2);还原那两行要注意均值的还原是乘 sig_y 再加 mu_y方差还原必须乘 sig_y 的平方因为方差是二阶矩。这个错会把置信区间整个算歪。模型训练完每个 model{q} 里保存着一组独立的 alpha、相关向量索引和噪声精度你可以直接看每个输出用了哪几个样本做支撑这就是 RVM 相对黑箱模型的可解释性来源。评估部分除了常规的 RMSE 和 MAE我强烈建议加一个区间覆盖率 PICP这是验证“自带方差”到底靠不靠谱的硬指标%% 4. 评估RMSE、MAPE 与预测区间覆盖率 RMSE sqrt(mean((Yte - Yp_te).^2, 1)); % 每个输出一个 RMSE MAPE mean(abs((Yte - Yp_te) ./ (Yte eps)), 1); upper Yp_te 1.96 * sqrt(Vp_te); % 95% 区间上界 lower Yp_te - 1.96 * sqrt(Vp_te); % 95% 区间下界 PICP mean(Yte lower Yte upper, 1); % 覆盖率PICP 的含义是测试样本里真实值落在预测区间内的比例。模型估计的方差如果是对的PICP 应该接近 95%。低于 85% 说明方差被低估高于 99% 说明方差过于保守。这个指标是 RVM 区别于普通回归分析结果的标志性输出也是你判断方差公式有没有写错的第一道检查。4. 落到数据上才会遇到的坑RVM 多输出回归排查笔记4.1 核宽度翻车同一份数据0.8 和 0.6 结果两样现象核宽度从 0.8 改成 0.6测试集 RMSE 直接恶化 30%相关向量数量也差了一倍。换一个宽度又恢复看起来完全没有规律。 原因RVM 的基函数是以每个训练样本为中心的 RBF宽度直接决定基函数的“作用半径”。宽度过小每个基函数只管住自己附近一小撮样本模型抓不住全局结构迭代时 alpha 更新很容易把大量基函数误剪掉宽度过大所有基函数长相趋同核矩阵近似奇异后验协方差数值不稳alpha 更新噪声变大。 解决不要靠单一经验值。把宽度当成一个超参数按下一章的交叉验证流程系统搜索。常见的稳妥区间是输入特征标准差的 0.1 到 3 倍比如标准化后的输入标准差是 1那就先试 0.3、0.5、0.8、1.2、1.5 这几个档看验证集 RMSE 选。核宽度不是玄学是你还没用搜索替代猜测。4.2 迭代到一半所有相关向量都被剪掉了现象程序报错“所有基函数都被剪掉”或者模型返回零个相关向量预测全是常数。 原因两类情况最常见。一是 beta 初值给得太大也就是噪声方差设得极小模型认为数据几乎无噪声强行拟合每一个点导致 gamma 普遍偏小alpha_new gamma / mu^2 整体偏大一轮剪枝就把基函数全清了。二是核宽度设得特别大核矩阵各列高度相关后验协方差矩阵近似奇异Sigma 对角元素异常gamma 算出来趋近 0。 解决beta 初值务必用 1 / var(y)这是最稳妥的起点表示“先认为噪声水平就是输出方差量级”。核宽度从输入标准差附近起搜别一上来就试 5、10 这类大值。另外代码里保留 isempty(alpha) 的保护剪空时返回上一轮模型的参数而不是让程序崩溃至少能保住一个可用模型做诊断。4.3 输出没归一化多输出回归结果被大数值目标带偏现象3 个输出训练完第一个输出的 RMSE 是 3.2第二个是 0.05第三个是 45。看平均 RMSE 觉得模型很差但其实第二个输出拟合得很好只是被大量纲输出淹没了。 原因三个输出量纲不同时模型在迭代中对每个输出独立建模理论上不会互相干扰但评估时如果把各输出 RMSE 简单平均大量纲输出直接主导数字。而如果训练时输出没标准化数值大的输出对应的 beta 初值就小收敛路径和质量也和小量纲输出不一样导致稀疏结构完全偏向大量纲输出。 解决训练和评估都在标准化后的尺度上进行最后评估还原到原始尺度后按每个输出分别报告 RMSE 和 MAPE不要只报一个平均数字。回归分析结果的多输出对比必须逐输出看指标这是最容易误读统计口径的位置。4.4 预测区间覆盖率只有六成漏了权重不确定性这一项现象测试集上 PICP 只有 60% 到 65%预测均值看着还行但区间明显偏窄大量真实值落在区间外。 原因var_pred 只写了 1/beta只包含了噪声方差漏掉了 phi * Sigma * phi 这一项。这一项代表权重后验不确定性对预测方差的贡献样本越少、核矩阵越病态这一项越大。小样本场景下它往往比噪声项还大漏掉它区间立刻就不够了。 解决var_pred 必须写成 1/beta sum((Phite * Sigma) .* Phite, 2)。检查方式就是算 PICP如果按 95% 置信度建模但覆盖率明显低于 90%先怀疑方差公式漏项。这是 RVM 实现里最容易出但最隐蔽的错误血泪经验。4.5 剪枝阈值设太狠稀疏度好看了精度垮了现象把所有 alpha 大于 1e6 的基函数都剪掉相关向量数量大幅减少训练速度快了但测试 RMSE 明显升高。把阈值放宽到 1e8精度又回来了。 原因剪枝阈值本质是“权重小到什么程度就认为它不存在”的截断点。设 1e6相当于 alpha 大于 1e6 权重就被压到 1e-6 以下这里面有部分基函数虽然权重很小但数量多加在一起对预测仍有贡献。RVM 的稀疏性追求的是“该剪的剪掉”不是“剪得越狠越好”。 解决剪枝阈值默认按 1e8 到 1e9 用不要为了扩大稀疏率去调低它。判断稀疏性是否合理要看精度有没有发生可接受的下降一般以测试 RMSE 上升不超过 5% 为界。如果确实追求极致稀疏优先改核宽度和增加迭代轮数而不是动剪枝阈值。5. 参数怎么设到底核参数选择与回归分析结果对比5.1 RVM 回归的三个必调参数与一组稳妥初值把整个流程抽象出来真正需要人盯的参数就三个核宽度、剪枝阈值、迭代终止容差。其它像 alpha 初值、beta 初值都有固定套路。下面这张表给出我常用的初值和调整范围参数默认初值调整范围说明核宽度 width1.0标准化后0.1 ~ 3 倍输入标准差影响最大必须搜索剪枝阈值 prune_th1e81e7 ~ 1e9低于 1e7 容易误剪迭代容差 tol1e-31e-4 ~ 1e-2越小迭代越久精度收益有限alpha 初值1全是 1不用调迭代会自行收敛beta 初值1 / var(y)不用调用输出方差估计做起点最稳最大迭代200100 ~ 500主要防死循环alpha 初值全设 1 是 Tipping 原始论文里的经典做法表示先验上所有权重都“可能存在”然后让数据自己决定谁留下来。beta 初值用 1/var(y) 是因为我们从“噪声量级与输出量级相当”这个中性假设出发比直接拍一个 0.1 或 100 要稳得多。实际调试时先固定剪枝阈值和容差只动核宽度等核宽度选定后再微调容差。5.2 用交叉验证挑核宽度别拍脑袋设参数核宽度的选择我一般用简单 K 折交叉验证对每个候选宽度算验证集平均 RMSE选最小的那个。注意验证集上做标准化时要复用训练折的均值和方差防止数据泄露。核心循环长这样%% 5. 交叉验证选核宽度 widths [0.3, 0.5, 0.8, 1.0, 1.2, 1.5, 2.0]; CV 5; cv_rmse zeros(numel(widths), CV); for wi 1:numel(widths) for k 1:CV % 这里把训练集切成 CV 份轮流让 1 份做验证 [Xcv_tr, Ycv_tr, Xcv_va, Ycv_va] cv_split(Xtr, Ytr, k, CV); % 对每个输出训练 RVM 并计算验证 RMSE多个输出取平均 rmse_sum 0; for q 1:Q mdl rvm_fit(Xcv_tr, Ycv_tr(:,q), Xcv_va, build_kernel, widths(wi), []); rmse_sum rmse_sum sqrt(mean((Ycv_va(:,q) - mdl.y_pred).^2)); end cv_rmse(wi, k) rmse_sum / Q; end end [~, best_wi] min(mean(cv_rmse, 2)); best_width widths(best_wi);这段代码有个隐含假设同一个核宽度对所有输出都适用。严格来说每个输出可以有自己的最优宽度但那样要调的参数变成 Q 倍收益通常不匹配成本。我的习惯是先用统一宽度找全局趋势如果某个输出的 RMSE 明显异常再单拎出来单独调。交叉验证选的宽度只代表“在这组数据上泛化风险最低”不代表理论最优所以选完还得回训练集全量重训一次用测试集做最终评估。5.3 和弹性网络、SVM 回归放在同一把尺子上比RVM 再强也需要基线对照否则回归分析结果的说服力不够。我通常放三条基线弹性网络ElasticNet作为稀疏线性基线SVM 回归作为核方法同类基线BP 神经网络作为非线性大模型基线。比较时铁律是同一份划分、同一次标准化、同一个评估函数谁也别占便宜。弹性网络适合看“线性假设到底够不够”如果 RVM 的 RMSE 只比弹性网络好 5%说明数据主要是线性的模型复杂度不值得上。SVM 回归适合看“核方法里有没有必要用稀疏贝叶斯”SVM 拟合通常很快但需要调 C 和 epsilon 两个额外参数还拿不到预测方差。BP 作为高压基线如果 BP 大调一轮还干不过 RVM说明样本量支撑不了复杂模型RVM 就是更值的选择。另外补一句边界如果输出不是连续数值而是删失时间比如设备寿命、患者生存期那要的是生存分析应该走 cox 回归分析那一套工具链而不是这份多输出回归代码。RVM 的多输出回归面向的是连续目标。5.4 回归分析结果里最值得关注的三个输出模型训练完不要只贴一张指标表。三样东西最能说明问题第一是相关向量清单和数量它能告诉你预测每个输出到底用了多少个支撑样本数量越少模型越省内存第二是逐输出的 RMSE、MAPE、PICP 三列对照表PICP 接近 95% 说明方差估计可靠第三是核宽度的交叉验证曲线它记录了选参过程评审时能说服别人“这个宽度是搜出来的不是蒙的”。这三个输出才是“值得照着做并投入”的判断依据。6. 更进一步把预测方差当成产品卖点前面所有工作都在把 RVM 当成一个“比线性回归准、比神经网络省事”的回归器用但只拿它做点预测等于买椟还珠——RVM 真正值钱的是那个方差输出。这个方差能直接落到业务里而且不需要额外写多少代码。第一个用法是区间预测。预测区间给的是“这个点一定准吗”的答案而不是“大概是多少”。电池 SOC 估计里客户要的不是一个孤零零的剩余容量数字而是“95% 概率落在某个区间里”。用 1.96 倍标准差上下界包出来的区间覆盖率算出来 93% 以上这个结果拿去和生产决策系统对接说服力远大于单点 RMSE。第二个用法是异常检测。如果新样本的预测方差突然比训练集平均水平大好几倍通常意味着这个样本落进了训练数据覆盖稀疏的区域也就是所谓的外推危险区。把方差排序前 5% 的样本单独抽出来人工确认比用固定阈值卡残差要靠谱因为残差大可能是噪声方差大才是模型“自己知道自己不知道”。第三个用法是主动学习。如果目标是不断扩充训练集那每一轮新采样应该优先挑预测方差最大的样本而不是随机补样本。这个策略在样本获取成本高的场景非常值钱。RVM 的方差天然反映样本稀疏度直接拿它当采样优先级即可。我个人的习惯是把 var_pred 归一化后和业务风险阈值联动超过阈值就触发告警这个逻辑比训练好的回归模型本身还耐用。如果你现在手里正好有一份多输入多输出的数据我的建议是先跑通最小实现拿到逐输出 RMSE 和 PICP再花一个下午做核宽度搜索然后对比一次弹性网络和 SVM 回归把结果表存下来。这套流程走完你对 RVM 值不值得用的判断会比读十篇文章都实在。希望帮到你。本文还有配套的精品资源点击获取
返回列表