☰
基于LSTM的锂电池SOH估计:特征提取与多输入单输出回归实战
2026/10/19 5:25:18 网站建设 项目流程

做锂电池SOH估计有些年头了,最早的项目里用的还是安时积分加OCV修正那套老办法,后来发现误差在低温和大倍率工况下实在压不住,才开始认真考虑数据驱动的思路。标题里这个方案——基于LSTM的SOH估计,配合电池特征提取,多输入单输出回归——是我在模拟项目X里完整跑通过的一条技术路线。我先把话放这儿:LSTM不是SOH估计的万能解,但如果你手里有一批完整的循环充放电数据,又想尽快得到一个能用的估计模型,这套组合是性价比很高的选择。想直接上手的人,这篇文章就是你的实操地图。

1. SOH估计为什么难,LSTM凭哪条优势入场

1.1 SOH的工程定义与测量困境

SOH(State of Health,健康状态)在工程上最常见的定义是当前最大可用容量与出厂额定容量的比值:

SOH = C_current / C_new × 100%

看起来就是一个除法,但麻烦在于C_current根本没法在线直接测。要准确拿到当前最大可用容量,标准做法是把电池充满再恒流放空,用安时积分算一遍,这个过程必须离线、独占设备、至少花掉两三个小时。车停在路边或者设备在运行当中,这个数就是拿不到的。所以SOH估计的本质问题是:在不能直接测容量的情况下,用能在线采集的电压、电流、温度信号,把容量的衰减趋势推断出来。

老化机理本身又特别复杂。负极SEI膜持续生长会消耗活性锂,析锂在低温大倍率下会加速,正极材料结构在反复嵌脱锂过程中会劣化,这些机理叠加在一起,让容量衰减曲线呈现出高度非线性的特征。同一批电芯,放电深度不同、环境温度不同、充放电倍率不同,衰减曲线就能走出完全不一样的形状。想用一套统一机理模型把这几种衰减路径同时刻画出来,难度非常大。

1.2 传统方法为什么在工程现场不好用

早年做SOH估计,主流思路可以分三类。第一类是等效电路模型加卡尔曼滤波:把电池等效成RC网络,在线辨识内阻、极化电容等参数,再让滤波器去跟踪容量状态。这个方法的问题在于模型结构一旦选定,就很难覆盖多工况下的动态特性,参数辨识在噪声大的现场信号里也经常发散。第二类是经验公式法,比如用幂函数或多项式拟合容量衰减趋势,处理同一工况下的数据还行,换个温度、换个倍率就明显失真。第三类是基于电化学阻抗谱的测量方法,精度确实高,但阻抗谱测量依赖专用设备,做不了在线实时估计,只能用于离线抽检。

这三类方法我在项目里都碰过,共同的痛点非常一致:要么模型结构太僵硬,要么依赖离线设备,要么精度没过关。后来我转向数据驱动,主要是因为项目里攒下了大量循环老化实测数据——从满电到放空,每个循环的电压、电流、温度曲线全都完整记录,这才有了做深度学习的底气。

1.3 LSTM切入的时机与前提条件

LSTM适合做SOH估计,核心原因是电池容量的退化过程具有很强的时间相关性。第n个循环的SOH不是孤立事件,它和前几十个甚至上百个循环的状态都有关联,这种缓慢漂移、受历史状态影响的过程,正是循环神经网络擅长捕捉的对象。LSTM通过输入门、遗忘门、输出门三个门控结构维护一条记忆通道,让梯度能沿着时间反向传播得足够远,从而学到"早期循环对当前容量的影响"这类长程依赖。

需要注意,LSTM入场有一个前提条件:你必须有足够多的、结构完整的循环数据。我在项目里一般拿单个电芯做实验,跑600到800个完整充放电循环,每个循环都留恒流充电段和放电段电压电流曲线,样本量能达到几百条。如果连完整循环数据都没有,纯粹靠电池下单体的电压来估计,LSTM能发挥的空间很有限,不如直接上简单的回归。

2. 特征提取:把充放电曲线变成LSTM能看懂的老化指纹

2.1 原始信号里藏着哪些老化信息

很多初学者拿到电池数据之后,直接把某个时刻的电压、电流往外一堆就喂给模型,结果训练的时候训练集表现很好,测试集上惨不忍睹。问题不在网络,在于特征没提好。原始信号各时间点之间的相关性极强,但信噪比不高,真正反映老化的信息量其实集中在几个特定阶段。

我在项目里最常用的几个原始信号是:恒流充电段的电压-时间曲线、放电段的容量-电压曲线、电芯表面温度曲线、以及充电结束时的截止压降。恒流充电段的电压曲线能反映内阻增长和极化特性,电池老化越严重,同样电流下的电压抬升就越快;放电段的容量-电压曲线直接对应可用容量的变化,是SOH最直观的镜子;表面温度曲线则用来修正温度对电化学过程的影响,特别是大倍率下的自发热。把这三个信号同时纳入输入,就是标题里"多输入"的第一层含义——输入不是单变量,而是一组多通道信号。

2.2 IC增量容量曲线与峰值特征

单独用电压曲线或容量曲线,信息还是太冗余。这里就用到增量容量分析(Incremental Capacity Analysis)。IC曲线的定义是dQ/dV,物理含义是电池在某个电压区间内能充入或释放的容量多少,它对正负极相变过程非常敏感,所以被业内称为电池老化的"指纹"。

计算方式不复杂:取低倍率(比如0.05C到0.2C)恒流充电段的电量Q和电压V序列,用差分近似微分:

% IC曲线计算:输入充电容量向量Q和电压向量V dQ = diff(Q); % 相邻采样点之间的容量增量 dV = diff(V); % 相邻采样点之间的电压增量 IC = dQ ./ dV; % 增量容量 % 用findpeaks提取峰值特征 [pks, locs] = findpeaks(IC, 'MinPeakProminence', 0.05);

随着电池老化,IC曲线的峰值会降低、峰位会漂移、峰面积会收缩。这三个特征一一对应到正负极活性物质损失和极化程度,物理意义明确。实测下来,IC峰值高度和SOH的相关系数能到0.95以上,比直接用某个电压点的值强太多。所以我在特征集里一定会包含:IC曲线的峰值高度、峰值对应电压、峰面积,再把原始电压曲线等间隔抽样后纳入序列,作为补充信息。

2.3 多输入特征矩阵的构造与对齐

LSTM处理序列数据时,输入是一个特征矩阵:每一行是一个特征通道,每一列是一个时间步。这就是题目里"多输入单输出"在数据结构上的落地形态。拿一个充电循环举例,我选恒流充电段的200个时间采样点,每个采样点上有5个特征(充电电压、充电电流、表面温度、IC值、累积容量),这个循环就变成一个5×200的矩阵。整个电池几百个循环,就有几百个这样的矩阵,每个矩阵对应一个SOH真值标签。

特征矩阵构造中最容易被忽略的是时间对齐。不同循环的充电时长不一样,老电池充得更久,直接取原始长度会导致序列长短不一。我的做法是先统一采样到等间隔时间轴,用interp1插值到固定长度,再做归一化。归一化一定要对每个特征通道单独做,否则不同量纲的特征会把LSTM的梯度带偏。电压是3到4伏量级,IC值可能只有零点几,温度又是几十度量级,混在一起不归一化,模型基本训不出来的。

3. 网络架构设计与Matlab搭建细节

3.1 多输入单输出网络的整体拓扑

明确了输入是"多通道序列、单个目标值"之后,网络结构就比较清晰了。我用的是这样一条链路:

layers = [ sequenceInputLayer(numFeatures) % 输入层,numFeatures为特征通道数 lstmLayer(128, 'OutputMode', 'last') % LSTM层,只保留最后一个时间步的输出 fullyConnectedLayer(64) % 全连接层 reluLayer % 激活 fullyConnectedLayer(1) % 输出层,单个神经元 regressionLayer % 回归损失 ];

这里最关键的设计决策是LSTM层的OutputMode设为'last'。这意味着LSTM读完整个200步序列之后,把最后一个时刻的隐藏状态作为整条序列的摘要,后续的全连接层再从这个摘要往SOH回归。如果设为'sequence',输出的是每个时间步的状态,那就要在最后接一个序列平均或全局池化,结构和损失函数都会更绕。对于"一条充电曲线估计一个SOH"这种时序-单值映射任务,OutputMode='last'是最顺手的选择。

中间的全连接层是给LSTM输出做非线性变换的机会,64个神经元在数百个样本的规模下不至于过拟合。如果数据量大、工况多,可以放宽到128;如果样本数不足200,我建议直接去掉这一层,让网络更瘦一点,防止把噪声都背下来。

3.2 网络参数选择的基本原则

隐藏单元数、层数、dropout这些参数,很多教程喜欢拍脑袋定。我的经验是结合样本量来倒推:LSTM层的参数量大约是4×(输入维度+隐藏单元数)×隐藏单元数,输入5个特征、128个隐藏单元时,光LSTM层就有约6.8万个参数。几百个样本对应几万个参数,本身已经偏紧张了,所以再加第二个LSTM层的做法我是不推荐的,堆层数在这种小样本场景下收益极低,反而更容易过拟合。

防过拟合主要靠三样东西:适度的隐藏单元数、dropout层、以及后面的早停策略。dropout我一般设在0.2到0.3之间,加在LSTM层输出之后、全连接层之前。注意Matlab里LSTM层本身不支持dropout参数,要在lstmLayer后面单独接一个dropoutLayer。

3.3 完整Matlab代码骨架

我把训练部分的核心代码完整贴出来,用的都是Deep Learning Toolbox的标准函数:

% 假设已经构造好: % XTrain: 1×N_train的cell数组,每个元素是5×T的特征矩阵 % YTrain: N_train×1的SOH标签向量(百分比数值,如90.5) % XVal、YVal为验证集,格式同上 numFeatures = 5; numHiddenUnits = 128; layers = [ sequenceInputLayer(numFeatures) lstmLayer(numHiddenUnits, 'OutputMode', 'last') dropoutLayer(0.2) fullyConnectedLayer(64) reluLayer fullyConnectedLayer(1) regressionLayer ]; options = trainingOptions('adam', ... 'MaxEpochs', 300, ... 'MiniBatchSize', 32, ... 'InitialLearnRate', 0.002, ... 'LearnRateSchedule', 'piecewise', ... 'LearnRateDropPeriod', 80, ... 'LearnRateDropFactor', 0.5, ... 'ValidationData', {XVal, YVal}, ... 'ValidationFrequency', 10, ... 'Verbose', 1, ... 'Plots', 'training-progress'); net = trainNetwork(XTrain, YTrain, layers, options); % 预测阶段 YPred = predict(net, XTest); save('lstm_soh_model.mat', 'net');

这套代码跑通之后,后面所有的调参、换特征、换门控结构,都只需要动上面的参数或层定义,非常方便迭代。

4. 训练流程:数据处理、划分策略与收敛监控

4.1 训练样本的组织形式

LSTM训练数据必须组织成"序列观测值"的格式。在Matlab里,每个观测样本是一个numFeatures×T的矩阵,所有样本放在一个cell数组里。例如500个循环,每个循环取200个采样点、5个特征通道,那么训练集就是1×400的cell数组,每个元素是5×200的单精度矩阵。

标签Y则是一个简单向量,第i个元素等于第i个循环算出的SOH真值。SOH真值怎么取?我是在每次满充之后用小倍率放电实测容量,除以额定容量得到的。这个值本身有一定测量误差,所以标签质量也有上限,你在评估模型精度时会发现,测试集上RMSE大概在1%左右,再想往下压就不是模型问题,而是标签噪声的天花板了。

4.2 数据划分:必须按时间序和按电芯分

这是很多论文不会写明白、但在工程上要命的一点。SOH退化数据绝对不能随机划分训练集和测试集。容量的衰减是单调且强自相关的,随机打乱划分后,测试集里的样本和训练集里的相邻循环高度相似,模型几乎是在"抄答案",测试指标虚高到失去参考意义。

我的划分习惯分两级别。第一级别是同电芯时序划分:取前80%循环做训练,后20%循环做测试,模拟"用新电池数据训练、预测老化的中后段"的场景。第二级别是跨电芯验证:用A电芯和B电芯的数据训练,在C电芯上测试,检验模型是否学到了通用的退化规律,而不是背下了某颗电芯的个性。跨电芯的RMSE通常比同电芯差一到两倍,这个差异本身就是你模型泛化性的镜子。训练网络时,我在训练集里再切出10%到15%做验证集,用来做早停和超参选择。

4.3 训练选项详解与收敛监控

trainingOptions里几个参数我逐个说一下我为什么这么设。求解器选adam,因为它在小批量、非平稳目标上比传统sgdm稳定,基本不需要调动量项。InitialLearnRate设0.002,对于几百样本的小数据集偏保守一点,避免一开始loss就跳飞。300个epoch配合LearnRateDropPeriod为80,意思是每80轮学习率减半,让模型在后期做精细收敛。ValidationFrequency设为10,让它每10轮在验证集上算一次RMSE,实时观察有没有过拟合。

实际训练的时候,我盯着'Plots'选项产生的训练进度图看两个东西:训练loss是否平滑下降、验证RMSE是否先降后升。验证RMSE开始连续若干轮上涨而训练loss还在下降,就是过拟合信号,这时就该停下来用验证集上最优的那一版权重做最终模型。Matlab在validation没有自动早停,我一般自己加一句判断,用验证集最优的轮次重新加载模型。

5. 评估结果解读:从指标到泛化性边界

5.1 回归任务的核心评估指标

SOH估计是回归问题,我习惯同时看四个指标:RMSE、MAE、R²和最大绝对误差。RMSE惩罚大误差,能体现整体稳定度;MAE更直观,工程上报告"平均偏差不到1%"容易沟通;R²衡量模型解释了多少方差;最大绝对误差则代表最坏情况,BMS报警阈值的设定必须根据它来,不能只看平均。

% 计算评估指标 err = YTest - YPred; RMSE = sqrt(mean(err.^2)); MAE = mean(abs(err)); R2 = 1 - sum(err.^2) / sum((YTest - mean(YTest)).^2); maxErr = max(abs(err));

这里有一个容易踩的坑:SOH曲线本身是一条光滑的衰减曲线,就算你用最简单的线性插值也能得到很低的RMSE,R²更是轻松上0.9。所以R²在这类任务上区分度不高,我真正看重的是跨电芯测试的RMSE和最大误差,这两个才能反映模型有没有学到老化的本质规律。

5.2 我在模拟项目X里测到的典型结果

拿我用的某款2Ah的18650三元电芯数据举例,同电芯时序划分的场景下,测试集RMSE大约在0.8%到1.2%,MAE在0.7%左右,最大误差不超过2.5%。跨电芯验证就明显更有区分度了,如果训练电芯和测试电芯是同一批次、同一老化条件,RMSE会落到2%到3%;如果测试电芯来自不同批次或不同温度工况,RMSE会直接升到4%甚至更高。这说明模型的边界很清晰:它能学到同一类电芯在相近工况下的老化共性,但迁移到全新电芯或极端工况时,会明显露出数据驱动的局限性。

评估场景RMSEMAE最大误差
同电芯时序划分0.8% - 1.2%0.7%左右< 2.5%
跨电芯同工况2% - 3%1.5% - 2%< 5%
跨电芯异工况4% - 6%3% - 4%> 8%

组里的同学一开始总想把跨工况误差压到2%以内,试了很多复杂网络都做不到。后来我们意识到,这不是模型不够强,而是训练数据根本没有覆盖高温低温和不同倍率的组合空间,模型连这些工况下的老化模式都没见过,怎么可能预测得准。后续只能靠扩充老化实验矩阵来补数据,网络本身已经没必要再改了。

5.3 泛化性边界与实际部署建议

基于这个结果,我对这个方案的定位是:适合做同一电池体系、同一运行工况域内的SOH趋势估计,可以直接嵌入BMS做在线预警参考;不适合做跨化学体系、跨工况大迁移的通用估计。如果要做多工况覆盖,必须确保训练数据里把这些工况全部包含进来,而且各工况样本数相对均衡,不能高温数据占90%、低温数据占10%,否则模型的所谓"平均表现"会被高温段掩盖,低温段实际误差会非常难看。

6. 实操避坑清单和调参建议

6.1 最隐蔽的坑:数据泄露

这是我在这个项目里栽过最惨的一次。第一次训练时为了省事,我把全部数据一起做了归一化,再用随机划分切训练集和测试集。结果测试集RMSE只有0.3%,我还以为模型已经优化到极致了。后来在做跨电芯验证时才发现问题:随机划分下,测试集里任何一个样本,它的相邻循环大概率都在训练集里,LSTM完全可以通过记忆相邻序列获得假信息;而全局归一化会把测试集的分布信息透传到训练过程,这两个问题叠加,把指标搞得极其漂亮。

正确的做法是:归一化参数只从训练集上拟合,然后固定这个参数去变换验证集和测试集;数据划分必须严格按时间序或按电芯编号切。检查方式也很简单,做一个对照实验:训练好的模型在同电芯随机划分上测一次,再在跨电芯划分上测一次,如果两个结果差得离谱,基本就是数据泄露没跑了。

6.2 序列长度与采样频率的选择

序列长度是另一个我以前反复调的点。一开始我把整个充电段都作为输入,序列长度拉到上千步,训练慢且结果不好。后来发现原因在于无用信息太多——恒流转恒压阶段的后半段电压几乎不动,特征区分度极低,白白增加计算负担。我最终选定的是恒流充电段从开始到截止电压附近的200个均匀采样点,这一个窗口内包含了极化、内阻增长、IC峰值等绝大部分老化信息。

如果原始数据的采样频率不一致,比如不同批次实验用的设备采样率不同,一定先统一到同一时基上再用interp1插值。这个细节不处理,LSTM会把时间间隔不一致当成真实的物理特征去学,模型很容易学到采样率差异而非老化规律。

6.3 几个不太明显但很有用的习惯

最后分享三个让我少走很多弯路的小习惯。第一,跑通基线模型之后再上LSTM。我用IC峰值特征做多元线性回归,先拿它做一条基线,LSTM模型必须显著优于这条基线才算有价值,否则就是杀鸡用牛刀。第二,训练过程中把每轮验证集RMSE的完整曲线存下来,而不是只看最终结果,这样能清楚看到过拟合从哪个epoch开始,帮助判断要不要改dropout或降低隐藏单元数。第三,模型部署时记得把归一化参数一起保存,我在命令行里用save('feature_stats.mat')把每通道的均值和标准差存下来,预测一个新循环时用同一套参数变换,否则部署阶段极容易出现输入分布偏移导致的预测异常。

这套流程跑熟之后,再回头看SOH估计这件事,其实难点从来不在LSTM本身,而在怎么把电池机理和数据结构对齐。特征提取、时序划分、归一化、评估口径,每一个环节都比选网络结构更影响最终结果。如果你们手上的数据和项目场景跟这篇文章描述的基本一致,直接按这个流程复现,应该能少走我当初走的那些弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询