
如果你在用 MATLAB 做数据分析或者正在准备数学建模、MathorCup 这类竞赛大概率会遇到一个共同需求既要预测又要优化。比如短途运输货量预测之后还要做车辆调度光伏功率超短期预测之后还要给出储能策略银行客户认购概率预测之后还要决定营销资源的投放优先顺序。这一类问题从来不是“只做预测”或者“只做优化”而是把两步串成一条完整的决策链路。神经网络擅长从历史数据中提取非线性规律遗传算法擅长在复杂搜索空间中找到近似最优解。这篇文章会把两者在 MATLAB 里的定位、组合方式、完整代码和常见坑一次讲清楚。先说结论在 MATLAB 环境中把神经网络工具箱和全局优化工具箱配合使用是工程技术人员快速搭建“预测 优化”闭环成本最低的方案之一。文章会依次解决三个问题神经网络负责解决哪一半问题遗传算法负责解决哪一半问题两者在 MATLAB 里如何组合落地。读完你可以跑通一个最小可用的 GA-BP 示例并把思路迁移到自己的预测与优化项目中。1. 为什么预测和优化要放在一起讲很多人在初学阶段会把“神经网络”和“遗传算法”当成两个完全无关的方向。神经网络属于机器学习遗传算法属于智能优化算法看起来确实不搭。但实际工程项目里这两者往往是同一个问题的前半段和后半段。以短途运输场景为例。运营方需要先预测未来一天各条线路的货量这是一个典型的时间序列回归问题适合用 BP 神经网络来做。货量预测出来之后车辆怎么调度、路线怎么安排、装载量怎么分配又是一个带约束的组合优化问题。这个阶段的目标函数可能不光滑、不可导甚至无法写出显式表达式传统梯度下降法根本用不上遗传算法反而很合适。再比如光伏电站。超短期光伏功率预测可以给调度系统提供未来 15 分钟到 4 小时的出力曲线。但预测出功率之后储能系统该在什么时段充电、什么时段放电又要根据电价、负荷和电池寿命等条件做优化决策。这就是很多 MATLAB 用户真正卡住的地方能用拟合工具画出一张漂亮的预测曲线但不知道怎么把预测结果变成优化决策。神经网络回答问题“未来是什么样”遗传算法回答问题“接下来怎么做”。两者合在一起才能覆盖“从数据到决策”的完整闭环。这篇文章最适合下面几类读者正在准备数学建模、MathorCup、研究生电子设计竞赛等赛事的队伍在工业现场做设备预测、负荷预测、参数寻优的算法工程师科研中需要先用模型预测、再做参数优化的研究生刚接触 MATLAB 工具箱、想用图形化加脚本方式快速验证思路的入门者。2. 核心概念神经网络与遗传算法的定位搞清楚两个算法各自解决什么问题比记住公式更重要。2.1 神经网络从历史数据中找出非线性规律神经网络本质上是一个“万能函数拟合器”。你不需要事先假设输入和输出之间是什么函数关系只需要给它大量的输入输出样本它会自动调整内部权重让网络输出不断逼近真实值。用一句话概括神经网络是一个参数化黑箱映射它从样本中学习规律然后对未知输入做出预测。BP 神经网络是最常用的前馈神经网络结构包含输入层、隐藏层和输出层。信号从输入层逐层向前传播得到预测值然后根据预测值与真实值的误差反向传播逐层更新权重。MATLAB 里的feedforwardnet就是用来创建这类网络的函数训练完成后可以用view(net)查看网络结构图。神经网络适合解决的问题有三类回归预测负荷、货量、功率、价格、销量分类识别故障类型、客户类别、图像分类非线性系统建模输入输出关系复杂且没有显式公式。不擅长的地方也很明显数据量太小容易过拟合模型可解释性差对特征质量敏感。另外如果数据本身毫无规律任何神经网络都救不回来。2.2 遗传算法在复杂空间里搜索最优解遗传算法是启发式搜索算法的一种。它模拟自然界的“优胜劣汰”机制一组候选解构成一个种群每个候选解就是一个个体用适应度函数评价个体的好坏好的个体更容易被选中进入下一代随后通过交叉、变异产生新个体。迭代多代后种群整体水平会逐步提高最终逼近最优解。用一句话概括遗传算法不依赖目标函数可导也不要求目标函数形式已知它只需要一个能评价候选解好坏的适应度函数。遗传算法适合解决以下问题目标函数非线性、不光滑、不可导变量是高维的或者包含整数、离散值搜索空间存在大量局部最优传统梯度法容易陷入其中没有成熟的解析解法只能靠搜索。不擅长的地方在于当问题规模特别大、约束条件特别复杂时计算时间会很长。而且遗传算法是启发式算法不能保证找到数学意义上的全局最优解通常需要多次运行取最好结果。2.3 两种算法为什么能组合神经网络和遗传算法至少可以在三个层面组合组合方式说明应用场景GA 优化网络初始权重先用遗传算法搜索一组较优权重再交给 BP 训练减少随机初始化带来的结果不稳定GA 优化网络结构搜索隐藏层数、神经元数量、学习率等超参数避免人工试参神经网络预测 GA 优化决策神经网络输出预测值遗传算法在预测值之上搜索最优方案货量预测与车辆调度、功率预测与储能策略本文会重点演示第一种和第三种先分别跑通 BP 预测和 GA 参数寻优再组合成一个完整的 GA-BP 示例。3. MATLAB 工具箱怎么选、什么时候选MATLAB 的神经网络相关功能早期叫 Neural Network Toolbox现在归属于 Deep Learning Toolbox。经典函数feedforwardnet、train、view、nftool都还保留面向回归、分类、时间序列预测足够用。全局优化工具箱叫 Global Optimization Toolbox提供遗传算法ga、粒子群particleswarm、模拟退火simulannealbnd等启发式求解器。其中ga是最常用、也最适合与神经网络配合的函数。用之前先明确自己的需求如果只是做 BP 网络、RBF 网络、LSTM 等学习任务神经网络工具箱够用如果要做参数寻优、组合优化、超参数搜索再引入全局优化工具箱如果数据量达到数十万、上百万级别且用图像、文本等非结构化数据MATLAB 也可以做但 Python 配合 PyTorch 和 TensorFlow 的生态更完整如果数据量在几千到几万条之间特征是数值型表格数据MATLAB 工具箱的封装成熟度更高写代码更快。判断标准很简单你的问题核心是“预测”还是“寻优”以及你的数据规模是否超过传统机器学习能处理的范围。4. 环境准备与工具箱确认本文示例以 MATLAB R2016a 之后的版本为例更早版本请查阅对应版本文档。具体版本以你的实际安装为准代码思路通用。打开 MATLAB 后先确认两个工具箱是否可用。在命令窗口输入% 检查神经网络工具箱 ver(nnet) % 检查全局优化工具箱 ver(globaloptim)如果显示对应的工具箱名称和版本信息说明已经安装。也可以直接执行下面的命令不报错就说明函数可用% 创建一个最小的神经网络用于测试工具箱 net feedforwardnet(10); disp(神经网络工具箱可用); % 调用 ga 帮助文档查看是否安装全局优化工具箱 help ga如果提示未定义函数或找不到工具箱可以先在 MATLAB 的 Add-On Explorer 中搜索安装对应工具箱。需要注意的是工具箱安装和许可证管理要以你所在机构的正版授权为准不同版本、不同授权类型的可用功能会有差异。建议为本文示例单独建一个目录比如D:\ga_bp_demo并把下面的脚本都放在这个目录下避免工作路径混乱。5. 实战一BP 神经网络预测——以时间序列预测为例这一节演示一个完整的 BP 神经网络回归预测流程。为了不依赖外部数据文件我们用带噪声的正弦函数构造演示数据。核心思路是把当前时刻之前的若干历史值作为特征预测下一个时刻的值这种处理方式在负荷预测、货量预测、功率预测里非常常见。5.1 构造数据与滑窗特征%% 文件demo_bp_predict.m % 生成演示数据正弦函数加噪声 rng(42); x linspace(0, 6*pi, 600); T sin(x) 0.1 * randn(size(x)); % 用过去 5 个时刻的值预测当前时刻 window 5; X zeros(length(T) - window, window); for i 1:window X(:, i) T(i:end - window i - 1); end T_predict T(window 1:end); % 划分训练集与测试集时间序列建议按顺序划分 n size(X, 1); trainNum floor(0.8 * n); X_train X(1:trainNum, :); T_train T_predict(1:trainNum); X_test X(trainNum 1:end, :); T_test T_predict(trainNum 1:end);这里有一个容易踩坑的地方时间序列预测不能像普通回归那样随机打乱数据后划分训练集和测试集否则会造成未来信息泄漏。上面的代码按时间顺序取前 80% 做训练、后 20% 做测试更符合实际场景。5.2 数据归一化神经网络中的激活函数对输入数值范围敏感如果不做归一化输入特征之间量级差异过大容易导致训练变慢甚至不收敛。这里使用mapminmax把数据映射到 [-1, 1] 区间% 归一化 [Xn_train, ps_input] mapminmax(X_train, -1, 1); [Tn_train, ps_output] mapminmax(T_train, -1, 1); % 对测试集使用训练集相同的归一化参数 Xn_test mapminmax(apply, X_test, ps_input);注意mapminmax默认按行处理而我们的样本是一行一个样本所以需要先转置。5.3 创建网络并训练% 创建前馈神经网络隐藏层为 10 个神经元 net feedforwardnet(10, trainlm); net.trainParam.epochs 500; net.trainParam.goal 1e-5; % 训练网络 net train(net, Xn_train, Tn_train);feedforwardnet的第一个参数是隐藏层大小第二个参数是训练函数。trainlm是 Levenberg-Marquardt 算法收敛快适合中小数据集。数据量很大时可以考虑换成trainscg。5.4 预测与评估% 预测 Yn_test net(Xn_test); Y_test mapminmax(reverse, Yn_test, ps_output); Y_test Y_test; % 评估指标 mse_test mean((Y_test - T_test).^2); r2 1 - sum((Y_test - T_test).^2) / sum((T_test - mean(T_test)).^2); fprintf(测试集 MSE%.6f\n, mse_test); fprintf(测试集 R2%.4f\n, r2); % 绘图 figure; plot(1:length(T_test), T_test, b-, LineWidth, 1.5); hold on; plot(1:length(T_test), Y_test, r--, LineWidth, 1.5); legend(真实值, 预测值); xlabel(样本序号); ylabel(目标值); title(BP 神经网络预测效果);运行后命令窗口会输出 MSE 和 R²同时弹出一张预测对比图。R² 越接近 1 说明模型拟合效果越好。对于演示数据通常 R² 可以达到 0.9 以上真实项目中的效果取决于数据质量。view(net)可以查看网络结构图这是理解 BP 网络结构最直观的方式也经常出现在论文和竞赛报告中。6. 实战二遗传算法参数寻优——ga 的基本用法这一节先用一个经典的多峰值测试函数演示ga的基本用法体会遗传算法的搜索能力。Rastrigin 函数是一个知名的非线性多峰测试函数函数表面有很多局部极小值点非常适合用来验证启发式算法的全局搜索能力%% 文件demo_ga_basic.m % Rastrigin 函数目标是最小化 fitnessfun (x) 10 * length(x) sum(x.^2 - 10 * cos(2 * pi * x), 2); nvars 5; % 变量个数 lb -5.12 * ones(1, nvars); % 下界 ub 5.12 * ones(1, nvars); % 上界 % 设置遗传算法参数 options optimoptions(ga, ... PopulationSize, 100, ... MaxGenerations, 200, ... Display, iter, ... PlotFcn, gaplotbestf); % 运行遗传算法 [x_best, fval_best] ga(fitnessfun, nvars, [], [], [], [], lb, ub, [], options); fprintf(最优解); disp(x_best); fprintf(最优值%.6f\n, fval_best);运行后命令窗口会显示每一代的迭代信息同时弹出最优适应度曲线。随着迭代进行最优值会不断下降并逐渐趋于稳定说明算法在收敛。ga函数的前几个参数含义需要记住ga(fitnessfun, nvars, A, b, Aeq, beq, lb, ub, nonlcon, options)fitnessfun适应度函数句柄输入是一个行向量输出是一个标量nvars变量个数A, b线性不等式约束Aeq, beq线性等式约束lb, ub变量上下界nonlcon非线性约束函数options用optimoptions(ga, ...)创建的选项。遗传算法的核心参数有几个参数作用建议经验PopulationSize种群个体数量通常取变量维数的 520 倍MaxGenerations最大迭代代数看收敛曲线不够就加大CrossoverFraction交叉概率一般取 0.8 左右MutationFcn变异函数默认值通常够用UseParallel是否并行计算数据量大时设为 true需要强调的是遗传算法是启发式算法不保证每次都找到全局最优解。实际工程中建议多运行几次取最好的结果或者增大种群规模和迭代代数。7. 进阶组合GA 优化 BP 神经网络权重如果你运行过几次 BP 网络一定会发现一个问题同样的数据、同样的代码每次训练出来的结果不完全一样。原因是 BP 网络的初始权重是随机生成的而随机初始点不同最终收敛位置就不同。遗传算法可以承担“初始权重搜索器”的角色先用 GA 在权重空间中搜索一组较优的初始权重再把它赋值给 BP 网络最后用 BP 自己精训练。7.1 适应度函数设计GA 的每个个体都是一组网络权重。适应度函数需要把这个权重向量还原成网络并计算前向传播的误差%% 文件ga_bp_mse.m function mse_val ga_bp_mse(w, X, T, net_template) % 将权重向量写入网络 net net_template; net setwb(net, w); % 前向传播计算误差 Y net(X); mse_val mean((Y(:) - T(:)).^2); endgetwb和setwb是神经网络工具箱提供的权重管理函数可以把网络的所有权重和偏置展开成一维向量也可以把一维向量写回网络。这两个函数是 GA 与 BP 组合的关键桥梁。7.2 完整 GA-BP 闭环示例%% 文件demo_ga_bp.m % 数据集使用和第 5 节相同的滑窗构造方式这里直接复用 rng(42); x linspace(0, 6*pi, 600); T sin(x) 0.1 * randn(size(x)); window 5; X zeros(length(T) - window, window); for i 1:window X(:, i) T(i:end - window i - 1); end T_predict T(window 1:end); n size(X, 1); trainNum floor(0.8 * n); X_train X(1:trainNum, :); T_train T_predict(1:trainNum); X_test X(trainNum 1:end, :); T_test T_predict(trainNum 1:end); % 归一化 [Xn_train, ps_input] mapminmax(X_train, -1, 1); [Tn_train, ps_output] mapminmax(T_train, -1, 1); Xn_test mapminmax(apply, X_test, ps_input); % 创建网络模板 hiddenNum 10; net_template feedforwardnet(hiddenNum, trainlm); net_template configure(net_template, Xn_train, Tn_train); % 待优化权重数量 paramNum numel(getwb(net_template)); % 遗传算法搜索初始权重 fitnessfun (w) ga_bp_mse(w, Xn_train, Tn_train, net_template); options optimoptions(ga, ... PopulationSize, 40, ... MaxGenerations, 80, ... Display, off); [w_best, fval_best] ga(fitnessfun, paramNum, [], [], [], [], ... -ones(1, paramNum), ones(1, paramNum), [], options); fprintf(GA 搜索到的最优初始权重适应度%.6f\n, fval_best); % 将 GA 结果写回网络再用 BP 精训练 net feedforwardnet(hiddenNum, trainlm); net configure(net, Xn_train, Tn_train); net setwb(net, w_best); net.trainParam.epochs 200; net.trainParam.goal 1e-5; net train(net, Xn_train, Tn_train); % 预测并评估 Yn_test net(Xn_test); Y_test mapminmax(reverse, Yn_test, ps_output); Y_test Y_test; mse_test mean((Y_test - T_test).^2); r2 1 - sum((Y_test - T_test).^2) / sum((T_test - mean(T_test)).^2); fprintf(GA-BP 测试集 MSE%.6f\n, mse_test); fprintf(GA-BP 测试集 R2%.4f\n, r2); % 绘图对比 figure; plot(1:length(T_test), T_test, b-, LineWidth, 1.5); hold on; plot(1:length(T_test), Y_test, r--, LineWidth, 1.5); legend(真实值, GA-BP 预测值); xlabel(样本序号); ylabel(目标值); title(GA-BP 神经网络预测效果);运行方式很简单把ga_bp_mse.m和demo_ga_bp.m放在同一目录运行demo_ga_bp.m。7.3 运行结果怎么判断