CPO-SVR:用冠豪猪优化算法给支持向量回归机"自动调参",一次预测多个指标
很多工程预测问题不是"一个输入一个输出",而是"多输入多输出":给定一批运行参数,要同时给出效率、能耗、成本等多个相互关联的指标。传统做法是对每个指标单独训练模型,但每个模型的超参数(惩罚系数、核参数)都靠人工试凑,费时且不保证最优。
本文以一组压缩机运行数据 为例,讲清楚一件事:如何用 2024 年提出的**冠豪猪优化算法(Crested Porcupine Optimizer,CPO)自动搜索支持向量回归(Support Vector Regression,SVR)**的最优超参数,并针对两个输出分别建模,实现多输入多输出预测。文末会给出真实实验数据:其中一个输出的测试集决定系数 R² 达到 0.9999。
一、研究背景:回归模型的两个痛点
SVR 是小样本、非线性回归的经典工具,建立在结构风险最小化之上,泛化能力好,很适合工程实测数据。但它的性能高度依赖两个超参数:
- 惩罚系数 C:权衡"拟合误差"与"模型复杂度"。C 过小欠拟合,过大易过拟合。
- 核参数 γ(RBF 高斯核):控制核的"宽度"。γ 越大核越窄、模型越复杂,越容易过拟合。
手动网格搜索或随机搜索要么算不动,要么陷入次优。启发式优化算法(PSO、GWO、GA 等)正好擅长这种"黑盒连续优化",其中冠豪猪优化算法 CPO 在探索与开发之间做了精巧的平衡,收敛快、不易早熟,很适合用来搜 SVR 的超参数。
另一方面,实际工程常有多个输出 (如效率与经济成本),它们共享同一组输入。直接训练一个多输出模型较复杂,工程上常用"每个输出独立建模"的拆解策略:对每个输出训练一个单输出 SVR,各自用 CPO 找各自的最优超参数。本文的代码采用的就是这条路线。
二、问题定义与数据
实验数据 数据集.xlsx 共 361 条样本、7 列,含义如下:
| 列 | 字段 | 含义 | 取值范围(约) |
|---|---|---|---|
| 1 | 编号 | 样本序号 | 1--361 |
| 2 | 转速 | 输入特征 x₁ | 540--660 |
| 3 | 余隙容积全关 | 输入特征 x₂ | 0.125--1.0 |
| 4 | 用户排气量 | 输入特征 x₃ | 0.0287--0.039 |
| 5 | 冷却水流量 | 输入特征 x₄ | 2.7--3.9 |
| 6 | 效率 | 输出 y₁ | 0.72--0.89 |
| 7 | 经济成本 | 输出 y₂ | 约 29 万--48 万 |
四个输入刻画的是压缩机的运行工况(转速、余隙、排气量、冷却水流量),两个输出分别是要预测的效率 与经济成本。这是一个典型的 4 输入、2 输出的回归任务,输出量纲差异极大:效率在 0~1 之间,经济成本在数十万量级,这也决定了后面评估指标要分开看。
三、技术路线

整体流程是一条"数据处理 → 多输出拆解 → CPO 寻优 → 训练 → 预测 → 评估"的流水线:
#mermaid-svg-CT7zFlOGte30hVDl{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CT7zFlOGte30hVDl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CT7zFlOGte30hVDl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CT7zFlOGte30hVDl .error-icon{fill:#552222;}#mermaid-svg-CT7zFlOGte30hVDl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CT7zFlOGte30hVDl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CT7zFlOGte30hVDl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CT7zFlOGte30hVDl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CT7zFlOGte30hVDl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CT7zFlOGte30hVDl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CT7zFlOGte30hVDl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CT7zFlOGte30hVDl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CT7zFlOGte30hVDl .marker.cross{stroke:#333333;}#mermaid-svg-CT7zFlOGte30hVDl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CT7zFlOGte30hVDl p{margin:0;}#mermaid-svg-CT7zFlOGte30hVDl .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CT7zFlOGte30hVDl .cluster-label text{fill:#333;}#mermaid-svg-CT7zFlOGte30hVDl .cluster-label span{color:#333;}#mermaid-svg-CT7zFlOGte30hVDl .cluster-label span p{background-color:transparent;}#mermaid-svg-CT7zFlOGte30hVDl .label text,#mermaid-svg-CT7zFlOGte30hVDl span{fill:#333;color:#333;}#mermaid-svg-CT7zFlOGte30hVDl .node rect,#mermaid-svg-CT7zFlOGte30hVDl .node circle,#mermaid-svg-CT7zFlOGte30hVDl .node ellipse,#mermaid-svg-CT7zFlOGte30hVDl .node polygon,#mermaid-svg-CT7zFlOGte30hVDl .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CT7zFlOGte30hVDl .rough-node .label text,#mermaid-svg-CT7zFlOGte30hVDl .node .label text,#mermaid-svg-CT7zFlOGte30hVDl .image-shape .label,#mermaid-svg-CT7zFlOGte30hVDl .icon-shape .label{text-anchor:middle;}#mermaid-svg-CT7zFlOGte30hVDl .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CT7zFlOGte30hVDl .rough-node .label,#mermaid-svg-CT7zFlOGte30hVDl .node .label,#mermaid-svg-CT7zFlOGte30hVDl .image-shape .label,#mermaid-svg-CT7zFlOGte30hVDl .icon-shape .label{text-align:center;}#mermaid-svg-CT7zFlOGte30hVDl .node.clickable{cursor:pointer;}#mermaid-svg-CT7zFlOGte30hVDl .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CT7zFlOGte30hVDl .arrowheadPath{fill:#333333;}#mermaid-svg-CT7zFlOGte30hVDl .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CT7zFlOGte30hVDl .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CT7zFlOGte30hVDl .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CT7zFlOGte30hVDl .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CT7zFlOGte30hVDl .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CT7zFlOGte30hVDl .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CT7zFlOGte30hVDl .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CT7zFlOGte30hVDl .cluster text{fill:#333;}#mermaid-svg-CT7zFlOGte30hVDl .cluster span{color:#333;}#mermaid-svg-CT7zFlOGte30hVDl div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CT7zFlOGte30hVDl .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CT7zFlOGte30hVDl rect.text{fill:none;stroke-width:0;}#mermaid-svg-CT7zFlOGte30hVDl .icon-shape,#mermaid-svg-CT7zFlOGte30hVDl .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CT7zFlOGte30hVDl .icon-shape p,#mermaid-svg-CT7zFlOGte30hVDl .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CT7zFlOGte30hVDl .icon-shape .label rect,#mermaid-svg-CT7zFlOGte30hVDl .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CT7zFlOGte30hVDl .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CT7zFlOGte30hVDl .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CT7zFlOGte30hVDl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 读取数据集.xlsx
拆分输入 X / 输出 Y
遍历每个输出 y_j
随机打乱, 80% 训练 / 20% 测试
mapminmax 归一化到 -1,1
定义适应度函数: 5折交叉验证MSE
CPO 搜索最优 C 与 gamma
用最优参数训练 epsilon-SVR
预测并反归一化
计算 RMSE/MAE/MAPE/R2
保存模型与评估结果







关键设计点在于第 6 步:把 C=2^c、γ=2^g 的对数 (c, g) 作为 CPO 的决策变量,适应度函数为 5 折交叉验证的均方误差(MSE)。用对数空间搜索,是因为 C 和 γ 合理的数量级跨度很大(从 2⁻¹⁰ 到 2¹⁰),对数变换能让搜索更均匀。
四、公式原理
4.1 支持向量回归(ε-SVR)
ε-SVR 的目标是找到一个"带宽为 ε 的管道",让尽可能多的样本落在管道内,落在管道外的样本才计损失。原问题写作:
minw,b,ξ,ξ∗12∥w∥2+C∑i=1n(ξi+ξi∗) \min_{w,b,\xi,\xi^*} \frac{1}{2}\|w\|^2 + C\sum_{i=1}^{n}(\xi_i+\xi_i^*) w,b,ξ,ξ∗min21∥w∥2+Ci=1∑n(ξi+ξi∗)
约束条件(对每个样本 i):
yi−(w⋅ϕ(xi)+b)≤ε+ξi,(w⋅ϕ(xi)+b)−yi≤ε+ξi∗,ξi,ξi∗≥0 y_i - (w\cdot\phi(x_i)+b) \le \varepsilon + \xi_i,\qquad (w\cdot\phi(x_i)+b) - y_i \le \varepsilon + \xi_i^*,\qquad \xi_i,\xi_i^* \ge 0 yi−(w⋅ϕ(xi)+b)≤ε+ξi,(w⋅ϕ(xi)+b)−yi≤ε+ξi∗,ξi,ξi∗≥0
其中第一项 ‖w‖²/2 是正则化项(结构风险),第二项是超出 ε 管道的误差惩罚,C 控制两者的平衡。通过拉格朗日对偶转化,并引入核技巧,最终回归函数只用支持向量表示:
f(x)=∑i=1n(αi−αi∗) K(xi,x)+b f(x) = \sum_{i=1}^{n}(\alpha_i - \alpha_i^*)\,K(x_i, x) + b f(x)=i=1∑n(αi−αi∗)K(xi,x)+b
本文选用 RBF 高斯核:
K(xi,xj)=exp(−γ ∥xi−xj∥2) K(x_i, x_j) = \exp\big(-\gamma\,\|x_i-x_j\|^2\big) K(xi,xj)=exp(−γ∥xi−xj∥2)
于是待优化的超参数就归结为 C 和 γ 两个标量,这正是 CPO 要搜索的对象。
4.2 冠豪猪优化算法(CPO)
CPO 由 Abdel-Basset 等人于 2024 年提出,灵感来自冠豪猪面对捕食者时由弱到强的四种防御行为:视觉、听觉、气味、物理攻击 。前两种对应算法的探索阶段 ,后两种对应开发阶段,通过随机选择防御策略实现探索与开发的动态平衡。
初始化:在搜索空间随机生成种群
Xi=lb+r⋅(ub−lb) X_i = lb + r\cdot(ub - lb) Xi=lb+r⋅(ub−lb)
循环种群缩减(CPR):模拟"只有部分个体受到威胁才激活防御"的现象,种群规模随迭代周期性收缩,以平衡探索与收敛:
N=Nmin+(N−Nmin)×(1−t mod (Tmax/T)Tmax/T) N = N_{\min} + (N - N_{\min})\times\left(1-\frac{t \bmod (T_{\max}/T)}{T_{\max}/T}\right) N=Nmin+(N−Nmin)×(1−Tmax/Ttmod(Tmax/T))
其中 N_min = 0.8N、周期 T = 2。
探索阶段(视觉 + 听觉) ,以全局最优 X_best 与随机个体 X_r 的中间点为参照:
视觉防御:
y=Xi+Xr2,Xit+1=Xit+randn⋅∣2 rand⋅Xbest−y∣ y = \frac{X_i + X_r}{2},\qquad X_i^{t+1} = X_i^t + \text{randn}\cdot\left|2\,\text{rand}\cdot X_{\text{best}} - y\right| y=2Xi+Xr,Xit+1=Xit+randn⋅∣2rand⋅Xbest−y∣
听觉防御(U₁ 为 0/1 掩码向量):
Xit+1=U1⋅Xit+(1−U1)⋅(y+rand⋅(Xr1−Xr2)) X_i^{t+1} = U_1\cdot X_i^t + (1-U_1)\cdot\big(y + \text{rand}\cdot(X_{r1}-X_{r2})\big) Xit+1=U1⋅Xit+(1−U1)⋅(y+rand⋅(Xr1−Xr2))
开发阶段(气味 + 物理攻击),引入随迭代衰减的因子:
Yt=2 rand⋅(1−tTmax)t/Tmax Y_t = 2\,\text{rand}\cdot\left(1-\frac{t}{T_{\max}}\right)^{t/T_{\max}} Yt=2rand⋅(1−Tmaxt)t/Tmax
气味防御用个体适应度与种群总适应度的比值作为"气味强度" S_t:
St=exp(fi∑f+eps),Xit+1=(1−U1)⋅Xit+U1⋅(Xr1+St⋅(Xr2−Xr3)−S) S_t = \exp\left(\frac{f_i}{\sum f + \text{eps}}\right),\qquad X_i^{t+1} = (1-U_1)\cdot X_i^t + U_1\cdot\big(X_{r1} + S_t\cdot(X_{r2}-X_{r3}) - S\big) St=exp(∑f+epsfi),Xit+1=(1−U1)⋅Xit+U1⋅(Xr1+St⋅(Xr2−Xr3)−S)
物理攻击是最强机制,直接以全局最优为锚点逼近:
Mt=exp(fi∑f+eps),Ft=rand⋅Mt⋅(−vt+Vtp) M_t = \exp\left(\frac{f_i}{\sum f + \text{eps}}\right),\qquad F_t = \text{rand}\cdot M_t\cdot(-v_t + V_{tp}) Mt=exp(∑f+epsfi),Ft=rand⋅Mt⋅(−vt+Vtp)
Xit+1=Xbest+(α(1−r2)+r2)⋅(U2⋅Xbest−Xit)−S X_i^{t+1} = X_{\text{best}} + \big(\alpha(1-r_2)+r_2\big)\cdot\big(U_2\cdot X_{\text{best}} - X_i^t\big) - S Xit+1=Xbest+(α(1−r2)+r2)⋅(U2⋅Xbest−Xit)−S
其中 α = 0.2 为收敛率,S = S·Y_t·F_t。每次更新后若越界则重新随机回搜索空间,并保留个体历史最优与全局最优。
五、算法步骤
- 数据准备 :读取 361×7 数据,取第 2--5 列为输入
X(4 维),第 6--7 列为输出Y(2 维)。 - 多输出拆解 :对每个输出
y_j(j=1,2)分别执行下述 3--8 步,各自得到一个独立模型。 - 划分数据:随机打乱后按 80/20 切分,得到 289 条训练、72 条测试样本。
- 归一化 :用
mapminmax将输入与输出都映射到 -1,1,训练集确定映射参数,测试集复用同一映射。 - 定义适应度函数 :以
(c, g)为决策变量,令C=2^c、γ=2^g,适应度为 5 折交叉验证的 MSE。 - CPO 寻优:初始化 20 个 2 维个体,迭代 10 代,按四种防御机制更新位置、处理越界、维护个体/全局最优,并执行 CPR 种群缩减。
- 训练最优模型 :用 CPO 找出的最优
(C, γ)训练 ε-SVR(RBF 核、ε=0.01)。 - 预测与反归一化:对训练、测试集预测,再反归一化回原始量纲。
- 评估:计算 RMSE、MAE、MAPE、R² 四项指标,保存模型、归一化参数与收敛曲线。
六、参数设定
| 参数 | 取值 | 说明 |
|---|---|---|
| 种群规模 nPop | 20 | CPO 初始个体数 |
| 最大迭代 MaxIt | 10 | 进化代数 |
| 决策变量维度 | 2 | 即 (c, g) |
| 搜索范围 | c, g ∈ -10, 10 | 对应 C、γ ∈ 2⁻¹⁰, 2¹⁰ |
| 核函数 | RBF(-t 2) |
高斯核 |
| 回归类型 | ε-SVR(-s 3) |
支持向量回归 |
| ε(管道宽度 p) | 0.01 | 回归容忍误差 |
| 交叉验证折数 v | 5 | 适应度计算方式 |
| 训练/测试比例 | 80% / 20% | 随机划分 |
| CPO 内部参数 | α=0.2, Tf=0.8, N_min=0.8N, T=2 | 收敛率 / 机制切换阈值 / 最小种群 / 周期 |
归一化采用 mapminmax 默认区间 -1,1。
七、主要功能与代码结构
工程包含一个主程序和四个核心函数,职责清晰:
| 文件 | 功能 |
|---|---|
main.m |
入口:读数据、按输出循环训练、画对比图与收敛曲线 |
CPO_SVR.m |
单输出 SVR 完整流程:划分、归一化、CPO 寻优、训练、预测、评估 |
fitSVM.m |
适应度函数:调用 LIBSVM 做 5 折交叉验证,返回 MSE |
CPO.m |
冠豪猪优化算法主体(含四种防御机制与 CPR) |
StatisticalParameter.m |
计算 RMSE、MAE、MAPE、R² 并打印 |
toolbox/ |
LIBSVM 编译好的 libsvmtrain/libsvmpredict.mexw64 等 |
主程序用 for i = 1:lie 遍历两个输出,每个输出调用一次 CPO_SVR,最终把两个模型存进 net.mat,并依次绘制每个输出的训练集对比图、测试集对比图和 CPO 收敛曲线。
八、运行环境
- 操作系统:Windows 10/11(64 位)
- MATLAB :R2016b 及以上版本(因附带的是 64 位 Windows 的
.mexw64二进制) - LIBSVM:3.x(已编译,无需自行编译)
- 工具箱 :Deep Learning Toolbox(旧版为 Neural Network Toolbox),用于
mapminmax - 硬件:CPU 即可,无需 GPU;数据量 361 条、迭代 10 代,秒级完成
运行前把工程解压到不含中文/空格的路径更稳妥,main.m 中已通过 addpath('toolbox\') 引入 LIBSVM。
九、实验结果与分析
从训练产物 net.mat 中读取到的真实结果如下:
| 输出 | 最优 C | 最优 γ | 训练 RMSE | 测试 RMSE | 训练 R² | 测试 R² | 测试 MAPE |
|---|---|---|---|---|---|---|---|
| 效率(y₁) | 11.73 | 1.18 | 0.0044 | 0.0095 | 0.9967 | 0.9847 | 0.80% |
| 经济成本(y₂) | 191.01 | 0.023 | 785.3 | 836.2 | 0.9999 | 0.9999 | 0.18% |
三点值得注意:
第一,两个输出的最优超参数差异很大。 效率需要中等 C(约 11.7)、较大 γ(约 1.18,核较"窄"、更精细);经济成本则需要大 C(约 191)、小 γ(约 0.023,核更"平滑")。如果两个输出共用一组超参数,必然顾此失彼,这从结果上印证了"每个输出独立建模"的必要性。
第二,评估必须看相对指标,不能只看 RMSE 绝对值。 效率的量纲在 0~1,测试 RMSE 0.0095 已经相当小;经济成本在数十万量级,RMSE 836 看着大,但折算成 MAPE 只有 0.18%。两个输出的 MAPE 与 R² 都处于优秀水平,说明模型整体拟合良好。
第三,两个输出的"可预测性"不同。 经济成本 R² 高达 0.9999、MAPE 仅 0.18%,说明运行参数与成本之间几乎是确定的映射关系;效率的测试 R² 为 0.9847,略低一些,且训练(0.9967)与测试(0.9847)之间存在一定泛化差距,说明效率与参数间的非线性更强、更难精确刻画。这也提示后续可以在效率这条输出上进一步改进。
收敛曲线方面,CPO 在 10 代内把交叉验证 MSE 稳定压到较低水平(效率输出约从 0.0060 降到 0.0046),验证了 CPO 的快速收敛能力。
十、应用场景
这套 CPO-SVR 多输入多输出方案可以平移到多种场景:
- 压缩机/空压机等装备的能耗与效率预测:输入工况参数,同时输出效率、成本等多指标,为运行调节提供依据。
- 多输出回归 / 多指标联合预测:只要多个目标共享同一组输入,即可套用"逐输出独立建模"的模板。
- 机器学习超参数自动寻优:把 CPO 换成对任意黑盒模型的超参数搜索,SVR 可替换为 GPR、XGBoost 等。
- 作为代理模型嵌入优化:预测模型可作为代理(surrogate)接入 NSGA-II 等多目标优化,反推最优工况(如文献中已用 CPO+SVM 做柴油机 SCR 尿素喷射优化)。
- 工程实测数据建模:小样本、强非线性、对泛化能力要求高的回归场景尤其适合 SVR。
十一、局限与改进方向
这套实现有三个可改进点,供读者延伸:
- 输出相关性未利用:逐输出独立建模忽略了效率与成本之间的耦合关系,可改用多输出支持向量回归(MSVR)或输出耦合正则化。
- 迭代次数偏保守:MaxIt=10 适合演示,实际问题可加大到几十代并配合早停。
- 超参数空间可扩展:目前只搜 C、γ,可把 ε(管道宽度)、交叉验证折数也纳入搜索,或换成贝叶斯优化做对比。
结语
CPO-SVR 的完整逻辑可以浓缩为一句话:把 SVR 的两个关键超参数放进对数空间,交给模拟冠豪猪防御行为的 CPO 去搜,再对每个输出各建一模型 。代码结构简单、可读性强,四行数据输入、两行数据输出,即可端到端跑通多输入多输出回归。读者若有自己的回归数据,替换 数据集.xlsx 并调整输入输出列号即可复用。