
简介该资源面向数据回归预测方向的学习者与研究者提供基于灰狼算法GWO优化径向基神经网络GWO-RBF的多变量输入预测方案重点解决RBF网络中心点、宽度参数与连接权重难以确定、预测精度受限的问题。压缩包共6个文件包含4个m脚本、1个txt说明文档与1个xlsx数据集整体约35KB其中脚本分别承担主流程、GWO寻优、初始化与目标函数计算说明文档记录使用方法与参数设置数据文件用于训练与验证演示。代码采用交叉验证提升泛化能力并给出R2、MAE、MSE、RMSE、MAPE等评价指标便于全面评估模型性能。目前已有57人学习适合希望快速复现GWO-RBF回归实验、替换自有数据开展对比研究或作为算法改进基础的读者参考。1. 从一组跑崩的回归预测说起GWO-RBF 到底解决什么问题去年帮一个做化工过程软测量的朋友看代码他用 MATLAB 的newrb搭了个 RBF 网络预测产品浓度训练集 R² 能到 0.96一换测试集直接掉到 0.71曲线画出来像心电图。问题不在数据在于 RBF 的隐层中心、扩散速度spread和输出权值全靠经验拍脑袋newrb的 goal 和 spread 两个参数稍微动一下结果就天差地别。这类玄学调参在单变量输入时还能靠试凑蒙过去一旦输入维度上到 6 维、8 维参数空间直接爆炸。灰狼算法优化径向基神经网络GWO-RBF就是冲着这个痛点来的。它把 RBF 里最难定的扩散速度 spread 当成优化变量用灰狼算法的社会等级机制去搜索最优值再拿这个 spread 训练网络做多变量回归预测。整套东西是 MATLAB 代码输入支持多列特征矩阵输出单列连续值适合做软测量、负荷预测、参数反演这类多输入单输出的回归任务。如果你手头有 MATLAB又正好被 RBF 的 spread 折磨过这份代码值得拆开看一遍。2. GWO 与 RBF 的咬合点为什么优化的是扩散速度2.1 RBF 网络里 spread 到底控制什么RBF 网络的结构分三层输入层、隐层、输出层。隐层每个神经元是一个径向基函数最常用的是高斯函数φ(x) exp(-||x - c||² / (2 * spread²))c是中心spread就是扩散速度也叫宽度、平滑因子。这个参数决定了基函数的胖瘦spread 太小每个神经元只管自己脚下一小块网络对训练点拟合得很死测试点一偏就失效典型的过拟合spread 太大所有基函数都摊成一片隐层失去区分能力网络退化成线性模型欠拟合。所以 spread 是 RBF 从能拟合到拟合得好之间的那个开关。MATLAB 里newrb(P, T, goal, spread)的 spread 默认给 1很多人直接不传结果就是上面说的测试集崩盘。手动调的话一般在一个数量级范围内试比如 0.1 到 10但多变量场景下这个范围和步长都不好定试凑成本很高。2.2 灰狼算法为什么适合干这件事灰狼算法Grey Wolf Optimizer, GWO是 Mirjalili 在 2014 年提出的一种群智能优化算法模仿灰狼群体的等级制度和围猎行为。狼群分 α、β、δ、ω 四级α 是头狼当前最优解β、δ 是次优解ω 跟着走。每次迭代ω 狼根据 α、β、δ 三只头狼的位置更新自己D |C * X_p(t) - X(t)| X(t1) X_p(t) - A * D其中A和C是系数向量A随迭代从 2 线性降到 0控制探索到开发的过渡C是随机扰动增加搜索多样性。选 GWO 而不是粒子群PSO或遗传算法GA来优化 spread有几个实际理由。第一GWO 要调的参数少主要就是种群规模和迭代次数不像 GA 要设交叉率、变异率一堆第二GWO 的收敛曲线通常比较平滑不容易在早期就卡在局部最优第三对于 spread 这种一维优化变量GWO 的搜索效率足够没必要上更重的算法。当然如果你的优化变量不止 spread 一个比如连隐层神经元个数一起优化GWO 也能扩展到多维但这份代码聚焦的就是 spread 单参数。2.3 适应度函数怎么定GWO 优化 spread得有个打分标准告诉狼群哪个 spread 好。回归预测里最直接的就是用验证集的均方根误差RMSE或者平均绝对误差MAE作为适应度。流程是每只狼代表一个候选 spread → 用这个 spread 训练 RBF → 在验证集上算 RMSE → RMSE 越小这只狼越接近 α。这里有个容易翻车的点如果适应度直接在训练集上算GWO 会把 spread 推向过拟合方向因为训练集 RMSE 可以无限小。所以必须划出验证集或者用交叉验证。代码里一般是按比例切分比如 70% 训练、15% 验证、15% 测试适应度用验证集 RMSE。3. 把代码跑起来数据准备、参数配置与训练主循环3.1 数据组织与归一化多变量输入意味着你的数据是一个矩阵行是样本列是特征最后一列是目标值。假设原始数据存在data.mat里变量名data格式是[样本数 × (特征数1)]。第一步是归一化因为 RBF 对输入尺度敏感不同量纲的特征混在一起会让距离计算失真。% 加载数据并归一化 load(data.mat); % data: [N x (D1)]最后一列为目标 X data(:, 1:end-1); % 输入特征 Y data(:, end); % 目标值 % mapminmax 归一化到 [-1, 1] [X_norm, ps_X] mapminmax(X, -1, 1); [Y_norm, ps_Y] mapminmax(Y, -1, 1); X_norm X_norm; % 转回 [N x D] Y_norm Y_norm; % 转回 [N x 1]mapminmax是 MATLAB 自带的归一化函数第三个和第四个参数指定目标区间。注意它默认按行处理所以要先转置。归一化参数ps_X、ps_Y必须保存预测新样本时要用同一套参数反归一化否则结果对不上。3.2 划分数据集% 按 70/15/15 划分训练、验证、测试 N size(X_norm, 1); idx randperm(N); n_train round(0.7 * N); n_val round(0.15 * N); train_idx idx(1:n_train); val_idx idx(n_train1 : n_trainn_val); test_idx idx(n_trainn_val1 : end); X_train X_norm(train_idx, :); Y_train Y_norm(train_idx, :); X_val X_norm(val_idx, :); Y_val Y_norm(val_idx, :); X_test X_norm(test_idx, :); Y_test Y_norm(test_idx, :);这里转置是因为newrb要求输入是[特征数 × 样本数]输出是[输出数 × 样本数]。randperm保证随机划分但如果你想让结果可复现在划分前加一句rng(42)固定随机种子。3.3 GWO 主循环与 RBF 训练这是整份代码的核心。GWO 的种群维度设为 1只优化 spread每只狼的位置就是一个候选 spread 值。% GWO 参数 SearchAgents_no 10; % 狼群规模 Max_iter 20; % 最大迭代次数 dim 1; % 优化维度spread lb 0.01; % spread 下界 ub 10; % spread 上界 % 初始化狼群位置 Positions rand(SearchAgents_no, dim) .* (ub - lb) lb; Alpha_pos zeros(1, dim); Alpha_score inf; Beta_pos zeros(1, dim); Beta_score inf; Delta_pos zeros(1, dim); Delta_score inf; for iter 1:Max_iter for i 1:SearchAgents_no spread Positions(i, :); % 用当前 spread 训练 RBF net newrb(X_train, Y_train, 0, spread, 50, 5); % 验证集预测 Y_pred_val sim(net, X_val); % 适应度验证集 RMSE fitness sqrt(mean((Y_pred_val(:) - Y_val(:)).^2)); % 更新 Alpha / Beta / Delta if fitness Alpha_score Alpha_score fitness; Alpha_pos spread; elseif fitness Beta_score Beta_score fitness; Beta_pos spread; elseif fitness Delta_score Delta_score fitness; Delta_pos spread; end end % 系数更新 a 2 - iter * (2 / Max_iter); for i 1:SearchAgents_no for j 1:dim r1 rand(); r2 rand(); A1 2*a*r1 - a; C1 2*r2; D_alpha abs(C1*Alpha_pos(j) - Positions(i,j)); X1 Alpha_pos(j) - A1*D_alpha; r1 rand(); r2 rand(); A2 2*a*r1 - a; C2 2*r2; D_beta abs(C2*Beta_pos(j) - Positions(i,j)); X2 Beta_pos(j) - A2*D_beta; r1 rand(); r2 rand(); A3 2*a*r1 - a; C3 2*r2; D_delta abs(C3*Delta_pos(j) - Positions(i,j)); X3 Delta_pos(j) - A3*D_delta; Positions(i,j) (X1 X2 X3) / 3; end end % 边界处理 Positions max(Positions, lb); Positions min(Positions, ub); fprintf(Iter %d: Alpha_score %.6f, spread %.4f\n, ... iter, Alpha_score, Alpha_pos); endnewrb的参数依次是输入、目标、均方误差目标0 表示不提前停止、spread、最大神经元数、每次添加的神经元数。这里goal设 0 是为了让网络充分训练MN设 50 限制隐层规模防止过拟合DF设 5 是每次迭代加 5 个神经元。GWO 部分a从 2 线性降到 0控制探索到开发的过渡。每只狼的位置更新综合了 α、β、δ 三只头狼的引导最后取平均。边界处理用简单的截断保证 spread 不跑出[lb, ub]。3.4 用最优 spread 做最终预测% 用 GWO 找到的最优 spread 训练最终模型 best_spread Alpha_pos; net_final newrb(X_train, Y_train, 0, best_spread, 50, 5); % 测试集预测 Y_pred_test_norm sim(net_final, X_test); % 反归一化 Y_pred_test mapminmax(reverse, Y_pred_test_norm, ps_Y); Y_test_real mapminmax(reverse, Y_test, ps_Y); % 评估指标 rmse sqrt(mean((Y_pred_test(:) - Y_test_real(:)).^2)); mae mean(abs(Y_pred_test(:) - Y_test_real(:))); r2 1 - sum((Y_test_real(:) - Y_pred_test(:)).^2) / ... sum((Y_test_real(:) - mean(Y_test_real(:))).^2); fprintf(Test RMSE %.4f, MAE %.4f, R2 %.4f\n, rmse, mae, r2);反归一化这一步不能省否则算出来的 RMSE 是归一化尺度下的没有物理意义。mapminmax(reverse, ...)用之前保存的ps_Y还原。4. 避坑与排查跑 GWO-RBF 最容易翻车的五个地方4.1 现象测试集 R² 是负数原因spread 被优化到极小值RBF 隐层神经元退化成一个个孤立的尖峰训练集完美拟合测试集完全失效。这是过拟合的典型表现。解决在 GWO 的适应度里加正则项或者给 spread 设一个合理下界。经验上lb不要低于 0.01如果数据归一化到[-1,1]spread 在 0.1 到 2 之间通常比较稳。另外把newrb的MN从 50 降到 20 到 30限制隐层规模。4.2 现象GWO 迭代曲线震荡不收敛原因狼群规模太小比如 5 只或者ub设得过大比如 100搜索空间太宽狼群在前期乱跑。解决SearchAgents_no至少给 10Max_iter给 20 到 50。ub根据数据尺度定归一化后 spread 超过 10 基本没意义。如果还震荡检查适应度函数是不是每次都在变——newrb本身有随机性同一 spread 两次训练结果可能不同这会让 GWO 误判。解决办法是在适应度计算前固定随机种子或者对同一 spread 跑 3 次取平均 RMSE。4.3 现象newrb报错 Inputs and targets have different numbers of samples原因newrb要求输入是[特征数 × 样本数]输出是[输出数 × 样本数]。很多人直接把[样本数 × 特征数]的矩阵传进去维度对不上。解决训练前统一转置。X_train X_norm(train_idx, :)Y_train Y_norm(train_idx, :)。养成习惯在newrb调用前用size检查一下两个矩阵的第二维是否相等。4.4 现象预测结果全是同一个值原因spread 太大所有隐层神经元的基函数都摊平了网络输出退化成常数。或者归一化时mapminmax的参数用错了反归一化后数值被压缩。解决检查 GWO 输出的best_spread是不是接近ub。如果是把ub调小。另外确认ps_Y是从训练集目标值算出来的不是从测试集算的——用测试集的参数反归一化训练集预测结果数值会错位。4.5 现象每次运行结果差异很大原因newrb内部有随机初始化GWO 的初始种群也是随机的两个随机源叠加导致每次跑出来的 spread 和最终指标都不一样。解决在代码开头加rng(42)固定全局随机种子。如果要做多次实验取统计量用for k 1:10, rng(k); ... end循环每次换种子最后报告均值±标准差。这样既保证可复现又能看出模型的稳定性。5. 进阶技巧把单参数优化扩展到多参数与交叉验证跑通基础版之后你可能会想能不能让 GWO 同时优化 spread 和隐层神经元个数答案是能把dim从 1 改成 2lb和ub改成两行适应度函数里同时用这两个参数训练 RBF。但要注意两个参数的搜索空间尺度不同spread 在 0.01 到 10神经元个数在 5 到 50直接放在同一个位置向量里GWO 的更新公式会对大尺度参数更敏感。常见做法是归一化到[0,1]再映射回各自范围。另一个实用技巧是用 K 折交叉验证代替单次验证集划分。单次划分的验证集 RMSE 波动大GWO 可能选到一个只对当前划分好的 spread。改成 5 折交叉验证适应度取 5 折 RMSE 的均值选出来的 spread 泛化性更稳。代价是计算量翻 5 倍但 GWO 本身迭代次数不多总体还能接受。% 5 折交叉验证适应度示例 K 5; cv cvpartition(N, KFold, K); fitness_cv 0; for k 1:K tr_idx training(cv, k); va_idx test(cv, k); net_k newrb(X_norm(tr_idx,:), Y_norm(tr_idx,:), 0, spread, 30, 5); Y_pred_k sim(net_k, X_norm(va_idx,:)); fitness_cv fitness_cv sqrt(mean((Y_pred_k(:) - Y_norm(va_idx,:)).^2)); end fitness fitness_cv / K;这段代码替换掉原来单次验证集的适应度计算即可。cvpartition是 MATLAB 统计工具箱的函数如果没有可以手写索引划分。验证 GWO-RBF 到底有没有效最直接的办法是跟固定 spread 的 RBF 对比。跑三组spread0.5、spread1、GWO 优化。在同一测试集上看 RMSE 和 R²。如果 GWO 组没有明显优于最好的固定值说明你的数据可能对 spread 不敏感或者 GWO 的搜索范围没设对。我一般会把这个对比表打印出来贴在实验记录里免得后面忘了当时为什么选 GWO。从那以后我每次拿到 RBF 相关的代码都强制先跑一遍固定 spread 的基线再上优化算法不然根本说不清提升到底来自哪里。希望这份拆解帮到你少走点调参的弯路。本文还有配套的精品资源点击获取