ARTICLE DETAIL

资讯详情

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

SSA-BP+NSGAII:麻雀搜索优化BP超参数与Pareto前沿

SSA-BP+NSGAII:麻雀搜索优化BP超参数与Pareto前沿 简介一套基于麻雀搜索算法SSA优化BP神经网络的多输入多输出回归预测并结合NSGA-II多目标遗传算法执行帕累托寻优的MATLAB完整源码与数据包面向机器学习与智能优化研究者、算法工程师及相关专业学生。资源共34个文件容量仅1.47MB其中19个m脚本覆盖SSA优化、NSGA-II遗传操作、成本计算与绘图等完整流程6个mat文件保存训练中间数据5个xlsx提供不同维度的输入输出示例与帕累托解集4张jpg直观展示预测拟合、误差及回归散点效果。目前已有92人学习下载。源码包含SSA优化BP初始权重阈值的实现并将优化前后的BP模型进行性能对比同时支持多输入多输出预测可运行获得帕累托最优解集及其对应自变量取值方便进一步分析工艺参数。整个包结构清晰、可直接运行适合作为复现实验、算法改进或工程应用的基础。1. 为什么说SSA-BPNSGAII这个组合值得你亲手搭一次同样一份多输入多输出的工业数据给三个工程师去搭BP结果能差出一倍以上的预测误差——BP神经网络结构图谁都会画可隐层节点数、学习率、正则化系数这三个超参数网格搜索要跑几百组手调基本靠玄学。SSA-BPNSGAII这个标题说的就是先用麻雀优化算法SSA把BP的超参数搜出来把多输入多输出预测模型做到验证集误差最小再用NSGA-II在“误差最小”和“模型复杂度最低”两个互相打架的目标之间找出Pareto折中曲线给决策者一张可选清单。适合手里有MATLAB数据、想直接跑出可复现结果的工程师——无论是设备剩余寿命预测、软测量还是多指标回归这套组合都适用。2. 麻雀优化算法为什么BP超参数值得交给SSA去搜BP的训练算法做的是参数寻优而BP本身的结构和训练配置是另一层优化问题。你很难用梯度去优化“隐层放几个神经元”因为离散变量不可导你也不愿意用网格搜索因为组合爆炸。麻雀优化算法是群智能算法里比较晚出现的一个它的价值在于把搜索过程分成了探索和开发两个节奏正好匹配BP超参数这种连续加离散的混合空间。2.1 BP神经网络结构里的三个要命超参数隐层节点、学习率、正则化把BP神经网络结构图展开看输入层节点数由特征列数决定输出层节点数由预测目标列数决定中间只有一行隐层神经元是你需要拍的板。隐层节点数太少模型欠拟合训练集误差都压不下去隐层节点数太多模型开始死记训练样本验证集误差不降反升。更麻烦的是它和学习率、正则化系数是耦合的——大网络配大学习率极易震荡小网络配大正则化又直接欠拟合。单独调任何一个参数都不难难在三个参数一起调。网格搜索在三维空间里按步长扫一遍最粗的粒度也要上百次训练随机搜索碰运气成分大贝叶斯优化对离散变量支持又一般。SSA这类群智能算法的优势在于它不依赖梯度信息直接把“一组超参数”当成一只麻雀的位置用种群迭代去逼近最优组合。麻雀算法对初始点不敏感也不容易像粒子群那样后期扎堆在一个局部峰附近这是它适合给BP当“调参器”的原因。2.2 SSA的发现者-加入者-警戒者机制MATLAB核心循环代码麻雀搜索算法的核心是把种群分成三类角色。发现者负责在较优区域附近小步搜索相当于局部开发加入者跟着发现者走同时有一部分会飞到更远的位置去探索相当于全局探索警戒者占比最小发现危险也就是意识到当前位置已经足够差时向最优位置靠拢或随机跳开避免整个种群过早收敛到一个坑里。三者比例通常按发现者占比、警戒者占比来设置其余都是加入者。下面这段就是我给SSA写的核心位置更新循环麻雀位置X的每一行是一组BP超参数维度dim3。function [bestX, bestF] ssa_search(fun, dim, lb, ub, N, iterMax) % fun: 适应度函数输入一组超参数x返回验证集MSE % dim: 超参数个数这里取3[隐层节点数, 学习率, 正则化系数] % N: 麻雀种群数iterMax: 最大迭代次数 PD round(N * 0.2); % 发现者数量占种群20% SD round(N * 0.1); % 警戒者数量占种群10% ST 0.8; % 预警阈值低于它时发现者小步走 X repmat(lb, N, 1) rand(N, dim) .* repmat(ub - lb, N, 1); X(:, 1) round(X(:, 1)); % 隐层节点数是整数 for i 1:N F(i) fun(X(i, :)); end [bestF, idx] min(F); bestX X(idx, :); for t 1:iterMax [~, sortIdx] sort(F); X_sorted X(sortIdx, :); f_worst F(sortIdx(end)); % 发现者更新 for i 1:PD alpha rand(); R2 rand(); % 随机预警值 if R2 ST % 安全小步走 X(i, :) X_sorted(i, :) .* exp(-i / (alpha * iterMax)); else % 发现危险向原点随机跳 X(i, :) X_sorted(i, :) randn(1, dim); end end % 加入者更新 for i PD1:N A randi([0 1], 1, dim) * 2 - 1; % 生成±1向量 A_plus A * inv(A * A 1e-10); % 伪逆防止奇异矩阵 if i N / 2 X(i, :) randn(1, dim) .* exp(-t / iterMax); else X(i, :) X_sorted(1, :) abs(X(i, :) - X_sorted(1, :)) * A_plus; end end % 警戒者更新 for i 1:SD j randi([1 N]); X(j, :) X(j, :) (2 * rand() - 1) .* abs(X(j, :) - bestX) ... ./ (F(j) - f_worst eps); end % 边界与整数约束 X max(X, repmat(lb, N, 1)); X min(X, repmat(ub, N, 1)); X(:, 1) round(X(:, 1)); % 重新评估适应度 for i 1:N F(i) fun(X(i, :)); if F(i) bestF bestF F(i); bestX X(i, :); end end end end代码里的关键是加入者更新用到了A_plus这个伪逆项。原论文里A是一个元素为1或-1的行向量A_plus A^T * (A * A^T)^{-1}目的是让加入者沿着靠近最优解的方向移动。当dim3时A*A^T是一个标量直接用inv不会报错但如果不加1e-10这个极小项一旦A全是1或者全是-1这个标量其实也没问题。真正会出问题的是后面我改写成矩阵形式时所以这个fudge factor建议保留。边界处理我这里直接剪裁到[lb, ub]隐层节点数单独用round取整。注意不要先剪裁再取整否则学习率、正则化这些连续变量会被round误伤。警戒者更新里我让所有警戒者都做了随机扰动没有按论文区分“当前最优个体”和“当前最差个体”两种情形实战中用这种简化版也能收敛而且代码更短。如果你要追求原版把警戒者的判断条件补上即可。2.3 SSA参数怎么设种群、发现者比例、预警阈值SSA的参数少但每个都影响收敛行为。我常用的初始配置如下参数默认值作用与调整建议种群数N30BP训练耗时时设20降耗时追求高精度设50发现者比例PD0.2 * N比例越大局部开发越强越小越容易错过最优警戒者比例SD0.1 * N比例太大种群会频繁随机跳收敛慢预警阈值ST0.8调大到0.9发现者几乎总是小步走调小发现者频繁跳远最大迭代iterMax30 ~ 50BP每次评估耗时长不建议超过50一个常见的翻车是把发现者比例调到0.5以上整个种群都在做局部小步搜索全局探索靠加入者根本拉不回来反过来把警戒者比例调到0.3每轮都有接近三分之一的个体会被随机跳开到后期最优解周围始终站不住人收敛精度很差。SSA的搜索节奏本质上靠这三个比例维持平衡我一般固定ST0.8、PD0.2N、SD0.1N只在种群数和迭代次数上做调整。3. NSGA-II多输出预测里误差与模型复杂度怎样同时优化把SSA-BP跑通后你会发现一个问题SSA返回的全局最优解往往是隐层节点数偏大的那个因为误差还能再压下去一点。但在工程现场一个隐层80个神经元的模型和一个隐层25个神经元的模型测试集误差差不到1%运维成本却差一倍。这时候单目标优化不够用需要NSGA-II把“误差”和“复杂度”同时摆上桌面。3.1 单一MSE为什么不够多输出场景下的目标冲突多输入多输出预测的MSE是所有输出列误差的均值这个指标本身没有错错在它只描述了一个目标。模型为了同时压住多列输出的总误差会把隐层撑大本质是用容量换精度。体现在训练曲线上就是训练集MSE一路下降验证集MSE降到某个拐点后开始回升这个拐点对应的隐层节点数才是工程上最划算的。NSGA-II处理的是目标冲突。这里我把两个目标定义为目标一是验证集MSE目标二是模型复杂度用隐层节点数加微小的训练耗时惩罚来表示。前者越小越好后者也越小越好但两者不可能同时最小——这就是标准的双目标最小化问题。NSGA-II会返回一组互不支配的解叫做Pareto前沿前沿上的每个点代表的都是一组可行的BP超参数决策者按现场约束去选。3.2 非支配排序和拥挤距离的MATLAB实现NSGA-II的核心是两个机制非支配排序负责把种群划成一层一层的Pareto前沿拥挤距离负责在同一层里保留那些“周围人少”的个体保证解的多样性。这两段代码是整个算法的心脏。function frontNo nondominated_sort(F) % F: N行M列的目标矩阵这里M2 N size(F, 1); domCount zeros(N, 1); % 被支配次数 dominatedSet cell(N, 1);% 支配的个体集合 frontNo zeros(N, 1); for p 1:N for q 1:N if p q, continue; end % p支配q的条件p的所有目标都不差且至少一个更优 if all(F(p, :) F(q, :)) any(F(p, :) F(q, :)) dominatedSet{p}(end 1) q; elseif all(F(q, :) F(p, :)) any(F(q, :) F(p, :)) domCount(p) domCount(p) 1; end end end front find(domCount 0); frontNo(front) 1; cur 1; while ~isempty(front) next []; for p front for q dominatedSet{p} domCount(q) domCount(q) - 1; if domCount(q) 0 frontNo(q) cur 1; next(end 1) q; end end end front next; cur cur 1; end end注意这段排序代码用的是经典的定义式写法两层循环遍历所有个体对复杂度是O(N^2)。当N30时完全没问题如果N超过100建议换成按目标排序的快速实现否则每代排序耗时不可忽略。非支配排序返回的frontNo数值越小表示这一层的个体越优。拥挤距离的处理更直接。对同一个前沿层内的个体按每个目标分别排序排序后相邻两个体目标差值的绝对值累加这一层的第一个和最后一个个体的距离直接设为无穷大保证边界点一定被保留。两个目标都算完后距离大的个体在锦标赛选择中更容易胜出这样下一代种群不会聚在一小撮区域里。3.3 NSGA-II主循环与参数两目标下的默认配置NSGA-II的主循环结构是固定的初始化种群、非支配排序、锦标赛选择、模拟二进制交叉SBX、多项式变异、父子合并、再次排序、截断到种群规模。接BP时目标函数是关键。function [f1, f2] bp_two_obj(x) % x [hidden, lr, reg]由NSGA-II传入 % 返回f1验证集MSE和f2模型复杂度 hidden round(x(1)); lr x(2); reg x(3); net feedforwardnet(hidden); net.trainFcn trainlm; net.trainParam.lr lr; net.trainParam.epochs 200; net.performParam.regularization reg; [net, ~] train(net, X_train, Y_train); y_val net(X_val); f1 mean((y_val - Y_val).^2, all); f2 hidden 0.001 * net.trainParam.time; % 复杂度隐层节点数耗时微惩罚 end训练函数用trainlmLevenberg-Marquardt小数据集上收敛速度远快于traingd。f2里把隐层节点数作为主项训练耗时只占千分之一的权重这样Pareto前沿横轴是隐层规模纵轴是验证集MSE十分直观。理想情况下前沿是一条向右下倾斜的曲线隐层越大MSE越低但降幅逐渐趋缓。NSGA-II要做的就是把这个曲线上每个有代表性的点都搜出来。NSGA-II本身的默认参数我列在这里照抄即可参数推荐值说明种群规模pop30配合BP评估耗时30是性价比折中迭代代数gen50再往上收益很小耗时翻倍交叉概率pc0.9SBX交叉接近1保持种群活跃变异概率pm1 / 变量数变量数为3时约为0.33交叉分布指数eta_c20越大子代越接近父代变异分布指数eta_m20同上控制变异步长4. 从原始数据到联合结果MATLAB完整流程与可复用代码前面两章把两块核心算法拆开了这一章把它们拼成一个能跑的流程。你在搜索引擎里翻过一堆matlab下载安装教程、甚至顺手看过免费python源码大全里别人用Python转写的版本之后会发现MATLAB原版的好处是把神经网络工具箱和优化循环直接焊在一起不需要自己手写BP。4.1 源码包组织与数据归一化拿到手先做什么一套完整的实现通常按这个结构组织一个主脚本负责读数据、调算法、出图两个寻优函数分别对应SSA和NSGA-II一个目标函数负责把超参数翻译成验证集误差最后是一个data.mat保存着全部输入输出数据。不建议把全部逻辑塞进一个脚本排错时你会后悔。数据准备阶段第一步是归一化。多输入多输出数据里各列量纲经常差着两三个数量级不归一化直接进BP训练过程会像蜗牛一样爬。% 数据准备X是n行p列输入Y是n行q列输出 rng(42); % 固定随机种子保证可复现 n size(X, 1); idx randperm(n); X_train X(idx(1:round(n*0.7)), :); X_val X(idx(round(n*0.7)1:round(n*0.85)), :); X_test X(idx(round(n*0.85)1:end), :); Y_train Y(idx(1:round(n*0.7)), :); Y_val Y(idx(round(n*0.7)1:round(n*0.85)), :); Y_test Y(idx(round(n*0.85)1:end), :); % 按列归一化到[-1,1]注意输出列也要单独归一化 [Xn, psX] mapminmax(X_train, -1, 1); [Yn, psY] mapminmax(Y_train, -1, 1); X_val_n mapminmax(apply, X_val, psX); Y_val_n mapminmax(apply, Y_val, psY); X_test_n mapminmax(apply, X_test, psX); Y_test_n mapminmax(apply, Y_test, psY);归一化有个细节必须只用训练集去计算mapminmax的映射参数验证集和测试集用同一组参数去做apply。如果三份数据各自归一化测试集的真实分布就被你人为扭曲了。Y也要归一化因为多输出的量纲千差万别不归一化会导致大数值的输出列在MSE里占绝对主导小数值输出列被模型无视。固定随机种子这件事容易被新手跳过。randperm和train函数内部都有随机性不固定种子同一套代码每次跑出的结果都不同你根本无法判断是算法改进还是随机噪声带来的提升。4.2 主脚本先跑SSA-BP单目标最优解的完整调用SSA-BP部分的主脚本很简单把第2章的ssa_search和BP训练目标函数拼起来。目标函数我建议单独写一个文件因为NSGA-II阶段还要复用同一套评估逻辑。% 主脚本SSA-BP阶段 dim 3; lb [5, 0.001, 1e-4]; % 隐层节点下限、最小学习率、最小正则化 ub [80, 0.1, 0.1]; % 隐层节点上限、最大学习率、最大正则化 N 30; iterMax 40; % 目标函数输入超参数返回验证集MSE fun (x) ssa_bp_cost(x, Xn, Yn, X_val_n, Y_val_n); [bestX, bestMSE] ssa_search(fun, dim, lb, ub, N, iterMax); fprintf(SSA-BP最优超参数: hidden%d, lr%.4f, reg%.4f, MSE%.4f\n, ... round(bestX(1)), bestX(2), bestX(3), bestMSE); % 用最优超参数重新训练最终模型 final_net train_final_bp(bestX, Xn, Yn);ssa_bp_cost函数内部的做法是把x拆分隐层节点取整用feedforwardnet创建网络设置好学习率和正则化系数在训练集上train然后在验证集上做一次sim并返回MSE。这里有个关键点——不要在每个个体上都设置trainParam.epochs为500BP本身带early stopping设200足够验证集误差连续6次不下降就会自动停。隐层节点数搜索区间的设置值得单独说。上一轮网格搜索的结果显示最优值在哪就把lb和ub收窄到哪附近完全没谱时用[5, 80]起步。区间设得太大SSA大部分迭代浪费在低质量区域区间设得太小又可能漏掉真实最优。暴力起始、迭代收窄是第一轮跑通的正道。4.3 主脚本再跑NSGA-IIPareto前沿和折中解怎么落地NSGA-II阶段需要把单目标函数替换成双目标函数。我用的做法是保留同一个BP训练逻辑只是多算一个复杂度指标。% 主脚本NSGA-II阶段 pop 30; gen 50; lb_nsga [5, 0.001, 1e-4]; ub_nsga [80, 0.1, 0.1]; % NSGA-II主循环简写完整实现见第3.3节 [popX, popF] nsga2_main(bp_two_obj, dim, lb_nsga, ub_nsga, pop, gen); % 画Pareto前沿 F1 popF(:, 1); F2 popF(:, 2); figure; scatter(F1, F2, 20, filled); xlabel(验证集MSE); ylabel(模型复杂度隐层节点数); title(SSA-BP NSGA-II 的Pareto前沿); saveas(gcf, pareto_front.png);popF里每一行是两个目标值每行对应的popX里是一组超参数。你会发现前沿左下角是“误差小但网络大”的解右上角是“网络小但误差稍大”的解两者都是非支配关系。决定选哪个要看业务现场的约束芯片内存有限就选右上角精度优先就选左下角其余选中间拐点处。这里我一般会把NSGA-II找到的Pareto前沿和SSA-BP的全局最优MSE叠加画在同一张图里。如果SSA-BP那个点落在Pareto前沿的左下角外侧说明SSA单目标搜索确实找到了误差最低的解但代价是隐层节点数很大如果SSA-BP那个点被Pareto前沿完全覆盖说明前沿上存在一个复杂度更低、误差也不差的解SSA的解直接可以淘汰。关于“多输入多输出预测结合多目标优化”的落地逻辑也就清楚了SSA-BP负责把预测模型做到误差下界NSGA-II在这个下界附近画一条权衡曲线。两步用的是同一批数据和同一种BP评估方式不存在模型不一致的问题。5. SSA-BPNSGAII的避坑清单5个常见翻车现场与修复这一章是我自己跑这套组合时踩过并花时间填平的坑按现象、原因、解决三步写照着排查能省下大量时间。5.1 中文注释乱码导致源码跑不起来现象从网上下载的MATLAB源码打开后中文注释全变成乱码有的直接报错有的运行到注释行时语法识别错误。原因MATLAB在R2021b之前默认按系统区域编码读取文件源码用UTF-8保存时中文注释在GBK环境里被错误解析。搜索热词里经常能看到“matlab 2023 的中文注释乱码”这类问题本质都是文件编码和编辑器编码不一致。解决统一用UTF-8保存源码文件。在MATLAB编辑器中打开文件确认右下角显示UTF-8如果显示GBK或ANSI用记事本或VS Code把文件另存为带BOM的UTF-8格式。运行前在MATLAB命令行执行feature(DefaultCharacterSet, UTF-8)只对当前会话有效重启后失效不如把文件编码改掉。如果你的MATLAB版本比较新直接在首选项里把编辑器默认编码改成UTF-8即可。5.2 位置更新冒出NaNA矩阵奇异问题现象SSA跑几轮之后适应度变成NaN最优解也变成NaN后续迭代全部崩溃。在命令行里看麻雀位置发现有些行全是NaN。原因加入者更新时计算A_plus A / (A * A)当A是零向量时AA0伪逆变成无穷大。更隐蔽的情况是A向量所有元素都为1或都为-1AA不为零但数值溢出。还有一个来源是发现者的指数更新exp(-i / (alpha * iterMax))当alpha非常接近0时指数项变成0整行位置被压成0后续乘以边界时出问题。解决在A_plus计算里加正则项A_plus A * inv(A * A 1e-10)在边界处理后再加一个isnan检查把任何含有NaN的行重新随机初始化。代码里加上这一段for i 1:N if any(isnan(X(i, :))) || any(isinf(X(i, :))) X(i, :) lb rand(1, dim) .* (ub - lb); X(i, 1) round(X(i, 1)); % 隐层节点数保持整数 end end5.3 适应度大起大落BP随机初始化与随机种子现象SSA连续跑两次最优MSE一个是0.02另一个是0.06差距大到没法判断算法有没有效果。甚至在同一次迭代中同一个麻雀位置前后两次评估的适应度都不一样。原因BP神经网络的权重和偏置每次train都随机初始化即使超参数完全相同训练结果也会有波动。SSA的适应度函数是基于单次训练结果的适应度不稳定整个种群的比较就没有意义。解决在SSA和NSGA-II的评估函数内部固定随机种子。但注意不能在函数最外层固定一次那会导致所有麻雀用同一组初始权重失去多样性。常见的做法是把随机种子和麻雀索引或评估序号绑定例如rng(x(1) * 100 x(2))同一组超参数每次评估结果一致。另一个办法是让每个候选解训练两次BP取平均MSE方差减半但训练时间翻倍建议在最终选点验证时用不在寻优过程中用。固定随机种子这件事本质上是给黑匣子开一个观察窗口——你总是希望看到算法真实收敛过程而不是被BP的随机性掩盖。5.4 NSGA-II耗时长到怀疑人生评估预算与缓存现象pop100、gen100的NSGA-II配置每代要训练100次BP每次训练几十秒跑完要几小时。有人想用matlab在线网页版直接跑结果所有进程在共享CPU上排队更慢半小时连第一代都算不完。原因BP训练本身耗时NSGA-II每一代都要对每个个体重新训练一遍BP评估次数等于pop * gen整体耗时等量放大。如果目标函数里还加了交叉验证那耗时直接再乘K倍。解决先把种群和代数降下来。pop20、gen30的配置配合快速训练一轮能压到十几分钟。再在评估函数里加缓存以超参数序列作为key把训练结果存到一个字典或者全局变量里同一组超参数被重复评估时直接读缓存。NSGA-II的交叉变异会产生大量重复超参数缓存命中率通常能到30%以上。实在要精细搜索用两阶段策略——先用小规模种群粗筛把Pareto前沿附近的区域找出来再在局部用细网格或小步长变异跑一轮。5.5 测试集误差放大归一化与反归一化不一致现象验证集MSE显示0.01测试集MSE却是0.15差了十几倍。单独看某个输出列的预测曲线整体形状对但幅值整体偏小。原因最常见的是反归一化时用错了映射参数。假设训练时输出的归一化范围是[-1, 1]反归一化必须用psY的原始映射关系。如果用测试集的输出值自己又做了一次mapminmax那预测值和真实值的尺度就对不上。另一个原因是数据划分不当——训练集和测试集的时间段分布差异大模型没见过测试集所在区间的数据特征。解决测试集评估时用训练集保存的psY做反归一化坚决不做第二次mapminmax。代码上这样写Y_pred sim(final_net, X_test_n); Y_pred_real mapminmax(reverse, Y_pred, psY); Y_test_real mapminmax(reverse, Y_test_n, psY); test_mse mean((Y_pred_real - Y_test_real).^2, all);这里Y_pred用的必须是归一化后的输出Y_test_n也是归一化后的真实值两者反归一化时都用psY尺度就对齐了。如果误差仍然很大去画每个输出列的误差分布直方图看到底是哪一列输出拉高了总误差再针对那一列单独加权重。6. 进阶用法把Pareto前沿变成工程决策表再下线6.1 用TOPSIS在Pareto前沿上选一个敢上线的解Pareto前沿上一般有七八个非支配解直接拍脑袋选一个不够严谨。我习惯用TOPSIS把多目标转成综合得分。对两个目标分别做正向化处理——MSE和复杂度都是越小越好所以直接取倒数或取反然后归一化再按欧氏距离计算每个解到理想解和负理想解的距离最终得分越高越优先。MATLAB里这段逻辑十几行就能写完跑完输出一张表每个解的隐层节点数、学习率、正则化系数、验证集MSE、综合排名。选出的折中解再拿到测试集上做滚动预测验证。所谓滚动预测是指把测试集按时间窗口切成长度固定的段每段用模型预测后半段然后窗口滑动最后统计所有预测误差的均值。这个方法能看出模型在连续时间上的稳定性避免只靠一个全局MSE被极端值带偏。方案验证集MSE隐层节点数单次训练耗时测试集MSE固定隐层12节点0.048123秒0.052SSA-BP最优解0.021648秒0.027NSGA-II折中解0.026284秒0.029NSGA-II最小复杂度解0.04082秒0.044这张表是典型的三方案对比。固定隐层是基线SSA-BP把误差压到最低但网络偏胖NSGA-II折中解牺牲了0.005的MSE换来了模型规模减半测试集上还更稳。在业务现场我通常会选折中解除非那个场景对预测精度的要求已经是“差0.01就停机”的程度。一个更高级的玩法是把SSA-BP的解作为NSGA-II种群的初始个体之一塞进去让Pareto前沿的端点自带一个强有力的候选。这样NSGA-II的搜索起点就不是纯随机前沿的覆盖范围会更完整。我现在拿到这类多输入多输出预测任务第一件事都是先跑SSA-BP拿到误差下界再用NSGA-II画权衡曲线最后把折中解拉到测试集上做滚动验证没有绝对最优解只有你能接受的误差和复杂度。希望帮到你。本文还有配套的精品资源点击获取
返回列表