遗传算法优化BP神经网络股票预测MATLAB源码实战
简介这份MATLAB源码资源面向具备一定机器学习基础、希望用遗传算法改进神经网络做股票价格预测的学习者与研究者。包内围绕BP神经网络与遗传算法的结合展开涵盖基础网络构建、遗传算法编码解码、适应度评估、模型对比以及PCA数据降维等环节可用于理解如何用进化方法优化网络结构与学习率等参数从而提升非线性时序预测的表现。资源共12个文件以6个m脚本、4个mat数据文件为主另含1个xls数据表与1个docx说明文档压缩包约415KB脚本负责建模与优化流程数据文件保存股票历史数据及优化后的网络参数便于直接运行与复现。目前已有291人学习下载。对于想掌握遗传算法优化神经网络完整实现思路、对照基础BP与GA-BP差异并做预测实验的读者这份源码提供了可参考的工程结构与调参排错线索。1. 遗传算法优化神经网络做股票预测一份 MATLAB 源码包能跑出什么股票预测这件事做过的人都懂最折磨人的不是模型不会写而是参数调不对。BP 神经网络本身结构不复杂但初始权值和阈值的选取极度依赖运气同一组数据跑两次结果可能差出一大截业内管这叫玄学初始化。这份 MATLAB 源码包的核心思路就是用遗传算法GA来替代随机初始化通过选择、交叉、变异把 BP 网络的初始权值和阈值先进化到一个比较好的起点再交给反向传播去精调。包里包含bp.m基础 BP 网络、bp_ga.mGA 优化后的 BP 网络、gadecod.m染色体解码、gabpEval.m适应度评估、pcaa.m主成分分析降维、duibi.m模型对比以及配套的.mat数据文件和 Excel 原始数据。适合正在做股票预测课程设计、毕设或者想搞清楚 GA 和神经网络怎么衔接的 MATLAB 用户。如果你之前跑 BP 网络总是陷入局部最优、预测曲线跟真实值差得离谱这套代码值得拆开看看。2. 拆开源码包GA 和 BP 到底在哪里对接2.1 先搞清楚遗传算法在优化什么很多人第一次接触遗传算法优化神经网络容易误以为 GA 是在优化网络结构——比如自动决定几层、每层几个节点。这份代码不是干这个的。它的做法是网络结构输入层、隐含层、输出层节点数由你手动指定GA 负责搜索一组最优的初始权值和阈值。具体来说所有连接权值和阈值被拉平成一个长向量这个向量就是一条染色体。gadecod.m的作用就是把这条染色体重新拆回权重矩阵和阈值向量喂给 BP 网络去前向计算。为什么这么做有效BP 网络用梯度下降训练损失函数是非凸的初始点落在不同的位置最终收敛到的局部极小值质量差别很大。GA 的全局搜索能力可以在训练开始前就把初始点撒到一个更优的区域相当于给梯度下降换了一个更好的起跑线。常见做法是种群规模设 20 到 50进化代数设 50 到 200但这些参数不是拍脑袋定的后面会讲怎么调。2.2 核心文件逐个拆从数据加载到结果对比拿到包之后先别急着跑bp_ga.m。按依赖关系理一遍执行链路% 第一步加载数据 % data.mat 里通常存的是归一化后的股票数据 load data.mat; % 包含输入特征矩阵和输出标签 load zh_bp.mat; % 基础 BP 网络的训练结果用于对比 % 第二步PCA 降维可选看 pcaa.m 的实现 % 如果输入特征维度太高先用 PCA 压一压 run pcaa.m; % 输出降维后的特征矩阵 % 第三步运行基础 BP 网络 run bp.m; % 训练标准 BP保存结果到 zh_bp.mat % 第四步运行 GA 优化的 BP 网络 run bp_ga.m; % 内部调用 gadecod.m 和 gabpEval.m % 第五步对比两种模型 run duibi.m; % 输出预测曲线对比、误差指标这段流程的逻辑是先建立基线纯 BP再用 GA 优化最后对比。bp.m里一般会设置训练次数、学习率、目标误差这些参数bp_ga.m则多了一层 GA 的封装。gadecod.m接收一条染色体向量按网络结构参数把它切分成inputWeights、hiddenBias、outputWeights、outputBias四部分然后赋值给网络。gabpEval.m接收同样的染色体调用解码后的网络做一次前向传播算出预测值和真实值的误差平方和取倒数作为适应度——误差越小适应度越高被选中繁殖的概率越大。2.3 数据文件和参数文件的对应关系包里几个.mat和.xls文件容易让人犯迷糊理一下文件名作用备注data.mat训练/测试用的股票历史数据通常是归一化后的矩阵数据.xls原始股票数据用于核对和重新生成 data.matzh_bp.mat基础 BP 网络训练后的权值和阈值对比基线gabp.matGA 优化后的网络参数核心输出zh_gabp.matGA-BP 的中间状态或最终结果可能包含进化过程记录gabpEval.m适应度函数决定进化方向gadecod.m染色体解码函数连接 GA 和 BP 的桥梁数据.xls是原始数据源data.mat是从它预处理归一化、划分训练测试集之后存下来的。如果你要换自己的股票数据改数据.xls然后重新跑预处理脚本生成新的data.mat就行。注意归一化方式要和原代码保持一致否则预测结果反归一化时会出问题。3. 跑通代码从环境配置到第一次出图3.1 MATLAB 版本选择和路径设置这套代码用的是经典 MATLAB 语法没有依赖 Deep Learning Toolbox 的新 API所以 MATLAB 2016b 以后的版本基本都能跑。但有两个坑要注意一是中文注释乱码问题MATLAB 2023 之后的版本对 GBK 编码的.m文件支持有变化如果打开bp_ga.m看到乱码用编辑器转成 UTF-8 再保存二是路径问题所有.m文件和.mat文件必须放在同一目录下或者把该目录添加到 MATLAB 的搜索路径里。% 在 MATLAB 命令行中设置工作路径 cd(D:\your_project_folder\ga_bp_stock); % 换成你的实际路径 addpath(genpath(pwd)); % 把当前目录及子目录加入搜索路径 % 验证文件是否齐全 dir(*.m); % 应该列出 bp.m, bp_ga.m, gadecod.m, gabpEval.m, pcaa.m, duibi.m dir(*.mat); % 应该列出 data.mat, zh_bp.mat, gabp.mat, zh_gabp.mataddpath(genpath(pwd))这行是把当前目录和所有子目录都加入搜索路径避免因为文件不在同一层而报 Undefined function 错误。如果你只把.m文件放一起但.mat在子文件夹里不加这行就会加载失败。3.2 关键参数在哪里改打开bp_ga.m你会看到几个需要根据自己数据调整的参数。常见做法是% GA 参数设置在 bp_ga.m 开头部分 popSize 30; % 种群规模一般 20-50 maxGen 100; % 进化代数一般 50-200 pc 0.7; % 交叉概率一般 0.4-0.9 pm 0.01; % 变异概率一般 0.001-0.1 % BP 网络结构参数 inputNum 10; % 输入层节点数取决于你的特征维度 hiddenNum 12; % 隐含层节点数常用公式 sqrt(inputoutput)1~10 outputNum 1; % 输出层节点数预测一个价格就是 1 % BP 训练参数 net.trainParam.epochs 1000; % 最大训练次数 net.trainParam.lr 0.01; % 学习率 net.trainParam.goal 1e-5; % 目标误差种群规模太小比如 10GA 搜索不充分优化效果不明显太大比如 100跑一次可能要十几分钟。进化代数同理50 代以内通常就能看到适应度曲线趋于平稳。交叉概率 0.7 是经典值变异概率 0.01 适合二进制编码如果你改成实数编码变异概率可以适当调大。隐含层节点数没有固定公式sqrt(inputNum outputNum) aa 取 1 到 10是常见经验但最终还是要靠试。3.3 运行顺序和结果查看按bp.m→bp_ga.m→duibi.m的顺序跑。bp.m跑完会生成或更新zh_bp.matbp_ga.m跑完生成gabp.matduibi.m读取这两个文件做对比。% 依次运行 run bp.m; % 观察命令行输出的 MSE 和训练曲线 run bp_ga.m; % 观察 GA 适应度进化曲线 run duibi.m; % 查看预测对比图duibi.m通常会画出两条预测曲线和一条真实值曲线横轴是时间测试集样本序号纵轴是价格。如果 GA-BP 的曲线明显比纯 BP 更贴近真实值说明优化起了作用。同时它会输出几个误差指标MAE、RMSE、MAPE。重点看 RMSE如果 GA-BP 的 RMSE 比纯 BP 低了 10% 以上这次优化就算有效。提示第一次跑建议把maxGen设小一点比如 20先确认流程能跑通再加大代数做正式实验。4. 避坑指南跑 GA-BP 最容易翻车的五个地方4.1 适应度函数返回 NaN 或 Inf现象gabpEval.m运行时报错或者 GA 进化曲线突然断掉。原因染色体解码后的权值太大导致网络前向传播时激活函数饱和输出变成 NaN。或者训练数据里有缺失值误差计算出 Inf。解决在gadecod.m里加一行权值范围限制把解码后的权值裁剪到[-5, 5]之间。同时检查data.mat里有没有 NaN用isnan()排查。4.2 GA 跑完了但预测效果还不如纯 BP现象duibi.m显示 GA-BP 的 RMSE 比纯 BP 还高。原因最常见的是适应度函数设计有问题。如果gabpEval.m里用的是训练集误差GA 可能过拟合训练集导致测试集表现差。另一个原因是进化代数不够GA 还没收敛就停了。解决把适应度改成验证集误差或者训练集和验证集误差的加权和。同时把maxGen加到 100 以上观察适应度曲线是否已经平稳。4.3 中文注释乱码导致语法错误现象打开.m文件看到一堆乱码运行时报 Invalid character 或 Unexpected MATLAB expression。原因MATLAB 2023 之后默认用 UTF-8 编码读取.m文件而老代码可能是 GBK 编码保存的。解决用 VS Code 或 Notepad 打开文件转成 UTF-8 编码再保存。或者在 MATLAB 里用feature(DefaultCharacterSet, GBK)临时切换但这不是长久之计。4.4 数据归一化方式不匹配现象预测结果反归一化后数值完全不对比如股票价格预测出来是负数或者几万。原因data.mat里的数据是用某种方式归一化的比如 mapminmax 到 [-1,1]但你在反归一化时用了错误的参数或者换了新数据但没重新计算归一化参数。解决找到原代码里归一化的地方确认用的是mapminmax还是手动(x-min)/(max-min)。换数据后必须用同样的方式重新归一化并保存 min/max 参数用于反归一化。4.5 训练集和测试集划分不合理现象模型在训练集上表现很好测试集一塌糊涂。原因股票数据是时间序列如果随机打乱划分训练测试集会造成未来数据泄露——用未来的数据预测过去。解决按时间顺序划分前 80% 做训练后 20% 做测试。不要用randperm随机打乱。如果原代码是随机划分的改成时间顺序划分再跑一遍。5. 进阶技巧用 PCA 降维和参数扫描把预测精度再提一档5.1 PCA 降维在股票预测里的实际作用pcaa.m这个文件容易被忽略但它在多因子股票预测里很关键。假设你用了 20 个技术指标作为输入特征这些指标之间往往高度相关比如不同周期的移动平均线直接喂给神经网络会导致维度灾难和过拟合。PCA 把这些相关特征压缩成几个正交的主成分通常保留 85% 到 95% 的方差就够了。% pcaa.m 的核心逻辑简化版 [coeff, score, latent] pca(features); % features 是 n×m 矩阵 explained cumsum(latent) / sum(latent); % 累计方差贡献率 k find(explained 0.9, 1); % 找到达到 90% 的主成分数 reduced score(:, 1:k); % 降维后的特征coeff是主成分方向score是投影后的数据latent是特征值。k是保留的主成分个数。降维后输入层节点数从 20 降到 5 左右训练速度明显加快过拟合风险也降低。但要注意PCA 是无监督的它不考虑主成分和预测目标的相关性。如果某个方差很小的主成分恰好对预测很重要PCA 会把它丢掉。常见做法是先用 PCA 降维再用 GA 优化 BP两步走。5.2 参数扫描用网格搜索找最优的隐含层节点数隐含层节点数对预测精度影响很大但没人能一次设对。我一般会写一个循环把候选节点数都跑一遍记录测试集 RMSE。hiddenCandidates [8, 10, 12, 14, 16, 18, 20]; rmseResults zeros(length(hiddenCandidates), 1); for i 1:length(hiddenCandidates) hiddenNum hiddenCandidates(i); % 重新初始化网络并训练 net newff(trainInput, trainOutput, hiddenNum); net.trainParam.showWindow false; % 不弹窗加快速度 net train(net, trainInput, trainOutput); pred sim(net, testInput); rmseResults(i) sqrt(mean((pred - testOutput).^2)); fprintf(Hidden%d, RMSE%.4f\n, hiddenNum, rmseResults(i)); end [bestRMSE, bestIdx] min(rmseResults); fprintf(最优隐含层节点数%dRMSE%.4f\n, hiddenCandidates(bestIdx), bestRMSE);这段代码的逻辑是对每个候选节点数重新构建网络、训练、在测试集上预测、算 RMSE。showWindow false是关掉训练窗口批量跑的时候能省不少时间。跑完之后bestIdx就是最优节点数。注意每次newff会重新随机初始化权值所以同一个节点数跑两次结果可能不同严谨的做法是每个节点数跑 3 到 5 次取平均。5.3 验证优化是否真的有效别只看一条曲线判断 GA 优化是否有效不能只看duibi.m画的那一张图。我一般会做三件事第一把 GA 的适应度进化曲线画出来看它是否收敛第二把纯 BP 和 GA-BP 各跑 10 次统计 RMSE 的均值和标准差GA-BP 应该均值更低且波动更小第三换一组没参与训练的时间段做外部验证看模型是否还有预测能力。% 多次运行统计对比 nRuns 10; rmseBP zeros(nRuns, 1); rmseGABP zeros(nRuns, 1); for i 1:nRuns run bp.m; rmseBP(i) calculateRMSE(zh_bp); run bp_ga.m; rmseGABP(i) calculateRMSE(gabp); end fprintf(BP RMSE: %.4f ± %.4f\n, mean(rmseBP), std(rmseBP)); fprintf(GA-BP RMSE: %.4f ± %.4f\n, mean(rmseGABP), std(rmseGABP));如果 GA-BP 的标准差明显小于纯 BP说明 GA 确实降低了模型对初始权值的敏感性这才是它最大的价值——不只是提高精度更是让结果可复现。从那以后我每次跑神经网络之前都强制先跑一遍 GA 做初始化哪怕精度提升只有几个百分点稳定性带来的收益也值了。希望这份源码包能帮你在股票预测的调参路上少走几个弯路。本文还有配套的精品资源点击获取