尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

NARX神经网络在电池SOC预测与BMS建模中的工程实践

NARX神经网络在电池SOC预测与BMS建模中的工程实践 简介面向电池时间序列预测场景提供基于NARX非线性自回归外生模型的Matlab完整源码与数据支持多输入、单输入以及单步、多步多种预测模式直接服务于电池状态估计、健康管理等相关回归任务。压缩包内含12个文件其中9个.mat文件存放不同SOC区间及UDDS工况下的模型验证数据2个.m脚本分别对应单输入与多输入NARX网络训练流程另有1个gitattributes辅助文件整体大小34.46MB。目前已有261人学习这套资源适合正在研究NARX网络在电池建模或时间序列预测应用的工程师和科研人员。借助所提供的电池单元模型与验证数据可按需切换预测步长快速复现NARX建模、训练与验证全流程缩短数据准备和调参周期。整套方案既便于初学者快速上手NARX建模也为进阶研究者提供了可扩展的对比实验框架。1. 这包源码真正值得看的是它的数据组织方式拿到这包电池 NARX 源码时最打动我的不是网络调参有多花哨而是作者把多输入、单输入、单步、多步这四种组合全拆成了独立脚本还按 SOC 区间单独放了验证集。做电池时间序列预测的人都知道市面上的 demo 多数只给你一组输入输出跑通一个单输入单步就结束了换到自己的工况数据立刻翻车。这包东西直接给了你 UDDS 工况下的 SOC90/10 验证文件等于把最难的数据拆分工作也一并做了。适合做 BMS 电池管理系统算法验证、SOC/电压估计、以及想快速在 Matlab 里搭 NARX 回归模型的人。用它之前你需要先理解一件事NARX 不是普通的回归网络它把历史输出也当成输入这一点对电池这种带强动态特性的被控对象至关重要。2. NARX 的回归本质为什么电池动态需要外生输入2.1 NARX 公式与开环/闭环模式NARXNonlinear AutoRegressive with eXogenous inputs的数学表达是y(t) f( y(t-1), ..., y(t-dy), x(t-1), ..., x(t-dx) )其中 x 是外生输入也就是你主动给电池的电流、温度这类激励y 是被预测变量比如端电压或 SOC。dy 和 dx 分别是输出延迟和输入延迟。电池电压对电流的响应不是瞬时完成的锂离子扩散、极化电压都有延时所以必须把过去多个时刻的电流和电压都作为特征。在 Matlab 中实现时开环和闭环是两种完全不同的用法。开环训练open loop把真实历史输出作为网络输入学习难度低适合做模型拟合闭环推理closed loop则把预测输出反馈回输入端适合真正的时间序列预测。很多人只跑开环训练误差看着不错一改成闭环就开始发散问题就出在延迟步数和数据预处理不一致。% 定义一个 2 步输入延迟、2 步反馈延迟的 NARX 网络 inputDelays 1:2; feedbackDelays 1:2; hiddenSizes 10; net narxnet(inputDelays, feedbackDelays, hiddenSizes); net.divideFcn divideblock; % 按时间顺序切分避免打乱时序这段代码的关键在于narxnet(inputDelays, feedbackDelays, hiddenSizes)。inputDelays 表示使用当前时刻之前 1 到 2 步的输入feedbackDelays 表示使用之前 1 到 2 步的输出。divideblock是按时间块划分训练集/验证集/测试集这是时间序列预测与普通回归最大的不同点不能随机打乱数据否则会使未来数据泄漏到训练集中。2.2 NARX 与普通前馈网络、LSTM 的对比同样做电池时间序列预测你也可以选择普通前馈网络或 LSTM。以下这张表可以帮助你决定什么时候该用 NARX对比维度NARX 神经网络普通前馈网络LSTM 网络记忆机制显式延迟反馈结构固定无记忆只能靠滑窗拼接门控单元内部状态记忆长度可变训练成本低几秒到几十秒低高需要大量数据和 GPU 或较长时间小样本适应性好几百组数据就能拟合一般差数据量少时很容易过拟合Matlab 原生支持直接通过 narxnet 构建feedforwardnet需 Deep Learning Toolbox 且版本较新可解释性延迟阶数和隐层节点可人工检查中等弱我见过不少团队用 LSTM 做电池 SOC 预测但最后部署时发现样本量不过几万条LSTM 反复调参才能压住验证集误差而 NARX 用同样数据在几分钟内就达到可用精度。如果你的数据只有几千到几万点且外部激励和响应之间有明确延迟关系建议先试 NARX 而不是直接上深度学习。Transformer 这类模型更是适合超长序列的全局依赖对电池这种指数衰减特征为主的系统反而有点大材小用。2.3 preparets 如何把原始时序变成监督学习矩阵Matlab 的 NARX 工具箱不会直接接受原始的时间序列向量它要通过preparets把输入和目标转换成带延迟的 cell 数组。很多新手在这里绕弯子明明数据是一列数字preparets却要求传入 cell。% 构造一个 1000 步的电流序列 x 和电压序列 y 示例 t 1:1000; x sin(t/10); % 模拟电流激励 y 0.5*x 0.2*([0; x(1:end-1)]) randn(1000,1)*0.01; % 模拟电压响应 X tonndata(x, false, false); T tonndata(y, false, false); net narxnet(1:2, 1:2, 10); [Xs, Xi, Ai, Ts] preparets(net, X, {}, T);tonndata把普通矩阵转换成 NARX 需要的 cell 序列。preparets返回的Xs是网络实际输入端Xi和Ai是初始输入延迟和初始层延迟状态Ts是目标值。{}这个位置是外部输入中的特殊占位单输入场景下没有额外反馈输入所以留空。参数false, false表示行和列方向都不做自动转置以免维度混乱。3. 拆解 .mat 数据流从 FDM 文件到 preparets 序列3.1 文件命名与训练/验证定位这个资源包里并不是只有一个数据文件FDM_N_50_fs.mat、ROM_battery_cell_SOC90_10.mat、Pade_validation_SOC90_10_UDDS.mat这些文件各有分工。按文件名推测FDM 可能是有限差分模型数据ROM 是降阶模型数据Pade 是帕德近似数据UDDS代表美国环保署城市道路循环工况。这一组文件里最重要的逻辑是不同 SOC 区间要分开验证因为电池在 SOC 90% 和 SOC 10% 附近的动态特性完全不同。文件名在训练/验证中的角色FDM_N_50_fs.mat主训练数据N50 可能表示 50 阶离散化或 50 个状态点fs 表示固定采样FDM_N_50_D_SOC90_10_UDDS.matSOC 90/10 区间的 UDDS 工况数据用于工况验证Pade_validation_SOC90_10_UDDS.mat基于 Pade 近似的 SOC 90/10 验证数据FDM_N_50_validation_1.mat / validation_2.mat额外验证集可用来测试模型泛化能力ROM_battery_cell_SOC90_10.mat降阶电池模型数据用于对比 NARX 拟合效果使用时应先分清哪些是训练用哪些是测试用。如果拿Pade_validation_SOC90_10_UDDS.mat去训练会在验证阶段得到虚高的精度。3.2 用 load 检查字段维度先看行到底代表什么加载任何.mat文件之前不要急着跑脚本。先用load和whos查看变量名和维度。这里最容易犯的错是把行当时间步或者把列当时间步。data load(FDM_N_50_fs.mat); whos(-file, FDM_N_50_fs.mat); % 假设能看到 input 和 target 两个变量 in data.input; tar data.target; disp(size(in)); % 例如 [2, 10000]表示 2 个输入通道10000 个时间步 disp(size(tar)); % 例如 [1, 10000]表示 1 个输出通道如果size(in)返回[2, 10000]意味着输入矩阵每一行是一个外生变量每一列是一个时间点。大多数 Matlab 神经网络工具箱函数按列处理时序所以内存中必须保持“行 特征列 时间步”的方向。若发现size(in)返回[10000, 2]在送入tonndata前要in in。3.3 preparets 标准工作流单步开环训练下面这段代码是在拿到真实.mat后最标准的处理流程。先加载数据再切分训练段和验证段然后定义 NARX 网络并调用preparets。load(FDM_N_50_fs.mat, input, target); X tonndata(input, false, false); T tonndata(target, false, false); trainEnd floor(0.8 * length(X)); X_train X(1:trainEnd); T_train T(1:trainEnd); X_val X(trainEnd1:end); T_val T(trainEnd1:end); net narxnet(1:2, 1:2, 15); net.trainFcn trainlm; [Xs, Xi, Ai, Ts] preparets(net, X_train, {}, T_train); net train(net, Xs, Ts, Xi, Ai);这里直接用X(1:trainEnd)截取 cell 数组Matlab 的 cell 数组是可以这样切片的。训练集占 80%验证集占 20%且验证集放在时间序列之后。trainlm是 Levenberg-Marquardt 算法适合中小规模 NARX 训练如果数据量较大或内存吃紧可以改用trainbr或trainscg。注意验证集必须跟在训练集之后不能用随机抽样切分。电池时间序列有自相关性随机抽样会把相邻时刻分别分到训练和验证中造成信息泄漏。4. 单输入与多输入建模两套脚本的取舍4.1 Run_Narx_Network.m 单输入主流程Run_Narx_Network.m对应的是单输入场景比如只用电流预测端电压。这种模型结构简单输入只有一路外生信号反馈延迟里保存着过去若干步的输出电压。% Run_Narx_Network.m 核心结构示意 load(FDM_N_50_fs.mat, current, voltage); x tonndata(current, false, false); t tonndata(voltage, false, false); net narxnet(1:3, 1:3, 12); net.divideFcn divideblock; net.divideParam.trainRatio 0.7; net.divideParam.valRatio 0.15; net.divideParam.testRatio 0.15; [Xs, Xi, Ai, Ts] preparets(net, x, {}, t); net train(net, Xs, Ts, Xi, Ai); % 开环测试 Y net(Xs, Xi, Ai); perf perform(net, Ts, Y);单输入的优势是输入变量少不容易把噪声带进模型。比如电流激励比较干净时单输入 NARX 就能很好拟合电压响应。但电池的端电压不仅仅由当前电流决定还受温度、SOC 区间、老化状态影响。如果只用电流做输入模型会把这些外部因素全部压进反馈延迟里训练起来隐层节点要更多。4.2 Run_Narx_Network_multi_input.m 多输入改造Run_Narx_Network_multi_input.m里做的是多输入模式比如同时把电流、电压、温度作为输入SOC 作为目标。NARX 的多输入只是把输入矩阵行数从 1 变成多行处理逻辑不变。% 多输入构造示例inputs 是 3 行矩阵每行一个通道 inputs [current; voltage; temperature]; target soc; X tonndata(inputs, false, false); T tonndata(target, false, false); net narxnet(1:2, 1:2, [10 5]); net.trainFcn trainlm; [Xs, Xi, Ai, Ts] preparets(net, X, {}, T); net train(net, Xs, Ts, Xi, Ai);多输入时narxnet的隐层参数改成了[10 5]意思是有两个隐层第一层 10 个神经元第二层 5 个神经元。多输入模型的优势在于提供给网络的外部信息更充分。比如在高倍率放电时电流不变但温度升高单输入模型可能把温度变化误判为电压异常多输入模型可以直接看到温度通道反馈延迟的压力就小很多。4.3 参数怎么定延迟阶数和隐层节点单输入和多输入的网络参数不能照搬需要看数据特征和采样频率。采样频率越高相邻时刻之间的相关性越强延迟阶数可以适当增加采样频率低延迟阶数太大反而引入过多历史噪声。参数单输入电流→电压多输入→SOC输入延迟 inputDelays1:2 或 1:31:2反馈延迟 feedbackDelays1:31:2隐层节点数10~20[10 5] 或 [15 8]训练函数trainlmtrainlm 或 trainbr数据归一化mapminmaxmapminmax如果训练时误差下降很慢优先减小延迟阶数而不是增加隐层节点。延迟阶数太大会造成网络需要记住过去很多步的细节泛化能力迅速下降。多输入模型有时会出现某个输入通道被学习到但另一个通道被忽略的情况你可以分别画出各通道的 y 对目标误差相关性来判断。5. 单步预测与多步预测从开环到闭环输出5.1 开环单步预测与误差指标开环单步预测是最简单也最容易达到高精度的模式每一步都使用真实的前一步输出来预测下一点网络不需要长时间保持自己的状态。这个模式适合做“在线估计”的每一拍修正比如 BMS 中每个采样周期拿到真实电压后预测下一时刻 SOC。% 开环单步预测 load(FDM_N_50_fs.mat, current, voltage); X tonndata(current, false, false); T tonndata(voltage, false, false); net narxnet(1:2, 1:2, 10); [Xs, Xi, Ai, Ts] preparets(net, X, {}, T); net train(net, Xs, Ts, Xi, Ai); Y net(Xs, Xi, Ai); Y_cell cell2mat(Y); T_cell cell2mat(Ts); rmse sqrt(mean((Y_cell - T_cell).^2));这里的net(Xs, Xi, Ai)调用是在开环状态下进行的因为net还没有被closeloop改写网络在预测每个时刻时都会接收到真实的历史输出作为输入依赖。对于这种模式RMSE 可以控制在很小范围但它并不能说明多步预测能力。如果验证集只有单步指标应额外做闭环测试。5.2 闭环网络与迭代预测多步预测必须把网络切换到闭环状态。闭环模式下网络不再接入真实历史输出而是把上一步预测出的结果反馈给反馈延迟输入这样才是一条真正的时间序列预测链路。netc closeloop(net); [Xs, Xi, Ai, Ts] preparets(netc, X(1:60), {}, T(1:60)); Yc netc(Xs, Xi, Ai); % 将预测结果转为普通矩阵并和真实值对比 Yc_cell cell2mat(Yc); T_full cell2mat(T(61:60length(Yc_cell)));closeloop返回一个新网络netc原来的开环网络net不受影响。这里只给网络 60 步的真实数据作为启动状态之后 60 步以后全部由预测值反馈。这样做才能考验模型在长期预测中的稳定性。常见问题是前几步还好越往后误差越大这是因为闭环后的误差会沿着反馈延迟累积。解决办法是把闭环步数控制在实际需要的最短范围内而不是无限预测。5.3 预测步长与延迟的工程约束实际工程中很少需要用闭环 NARX 一直预测到几百步以后。电池系统的激励在不停变化长时间闭环相当于让模型在没有外部信息更新的情况下自说自话误差必然累积。更合理的做法是每 N 步用真实测量值重置一次反馈状态。预测场景推荐闭环步数输入延迟反馈延迟SOC 在线估计修正1~5 步1:21:2短时电压预测10~30 步1:31:3工况片段预测60~100 步1:41:4闭环步数越长反馈延迟阶数就要越保守。我一般会在验证集上把“开环 RMSE”和“闭环 RMSE”同时打印出来如果闭环 RMSE 超过开环 RMSE 一倍以上就先降低反馈延迟再看是否数据分段不一致导致的。6. 用验证集校准电池模型UDDS 工况下的检查清单6.1 验证脚本跑到什么程度算通过拿到Pade_validation_SOC90_10_UDDS.mat或FDM_N_50_D_SOC90_10_UDDS.mat后不要只算一个总误差要分 SOC 区间看。电池在 SOC 90% 端的极化特性和 SOC 10% 端完全不同总 RMSE 很小但某个区间误差很大的情况很常见。建议把预测结果和真实 SOC 曲线画在同一张图上再打印 90% 区间和 10% 区间各自的 RMSE。load(Pade_validation_SOC90_10_UDDS.mat, input, soc); X_val tonndata(input, false, false); T_val tonndata(soc, false, false); netc closeloop(net); [Xs, Xi, Ai, Ts] preparets(netc, X_val, {}, T_val); Y_val netc(Xs, Xi, Ai); y_mat cell2mat(Y_val); t_mat cell2mat(Ts); r corrcoef(y_mat, t_mat); disp(r(1,2));corrcoef返回的相关系数可以作为整体相关性的快速检查。但相关系数高并不代表误差小所以还要看 RMSE 和最大绝对误差。如果最大绝对误差集中在某个 SOC 跳变点可以考虑在训练数据中增加该区间的样本占比。6.2 三个高频报错和对应处理运行这套源码时最常见的不是算法问题而是数据加载和维度错误。报错现象可能原因处理方法Preparets 报告“input targets size mismatch”输入和目标的 cell 长度不一致检查两个 cell 是否为同一列数截取相同区间训练时内存不足或运行极慢延迟阶数过大或数据过长降低 inputDelays/feedbackDelays或把数据下采样closeloop 后 predict 结果全是常数闭环启动状态太短网络还没建立有效反馈增加初始真实序列长度通常需要至少 20~50 步如果你是在新版 Matlab 上跑旧代码还需要注意narxnet是否被narnet相关函数替代。旧脚本中的net.trainFcn traingdx在新版中可能不再支持换成trainlm是最稳妥的兼容方案。6.3 把训练好的 NARX 导成 Simulink 模块并部署到 BMS最后给你一个可以直接用的技巧训练完成后用gensim把闭环网络导出成 Simulink 模块这会省掉大量手写部署代码。netc closeloop(net); gensim(netc, -1);gensim的-1表示生成一个离散采样步长为 1 的 Simulink 模块。生成后你可以把电流、温度等外生输入接到模块输入端SOC 或电压预测值从输出端取走。部署到 BMS 时只需要在每个采样周期把模块的预测结果和实际测量值做一次融合修正避免长时间开环漂移。这个方式比把 LSTM 导出到嵌入式环境要方便很多因为 NARX 模型本质上是带延迟的多层感知器生成的 Simulink 模块可以直接生成 C 代码。你在验证脚本里看到的FDM_N_50_fs.mat这类数据配合上面这几步就能构成一套从离线训练到在线预测的完整电池模型链路。本文还有配套的精品资源点击获取
返回列表