电池SOC估算案例1]:使用深度学习方法的锂电池SOC估算学习案例(基于LSTM与GRU算法...
[电池SOC估算案例1]: 使用深度学习方法锂电池soc估算学习案例(使用matlab完成) 1.基于循环神经网络(长短时记忆神经网络LSTM)的锂离子电池soc估算方法,电压电流作为输入,soc作为输出。 2.使用马里兰18650电池数据集完成,其中选择dst,bjdst, fuds工况数据作为训练集,us06工况作为测试集。 3.可帮助修改为基于门控循环单元GRU的soc估算。 4.可提供该马里兰18650数据集的处理代码,并进行简单。
锂电池的荷电状态(SOC)估算是BMS系统的核心能力之一。最近尝试用马里兰大学18650电池数据集搞了个LSTM模型,效果挺有意思。直接上干货,说说具体怎么操作的。

数据准备那些事儿:这个数据集里的工况类型很多,选训练集的时候挑了DST、BJDST、FUDS这三个动态工况。测试集单独留了US06工况,模拟车辆急加速场景。原始数据是CSV格式,用Matlab处理起来还算方便:
% 加载数据并筛选工况
raw_data = readtable('UM18650_15C.csv');
train_condition = ismember(raw_data.Profile, {'DST','BJDST','FUDS'});
test_condition = strcmp(raw_data.Profile, 'US06');
% 电压电流数据归一化
voltage = normalize(raw_data.Voltage);
current = normalize(raw_data.Current);
soc = raw_data.SOC; % 目标值本身在0-1范围
这里注意SOC值本身已经是0-1之间的数值,不需要额外处理。电压电流用z-score标准化可以加快模型收敛,特别是不同量纲的数据混在一起时。
搭建LSTM网络时试过不同层数结构,最终用双层LSTM效果比较稳定。Matlab的深度学习工具箱比想象中好用:
layers = [...
sequenceInputLayer(2) % 输入电压电流两个参数
lstmLayer(128,'OutputMode','sequence')
dropoutLayer(0.2)
lstmLayer(64)
fullyConnectedLayer(1)
regressionLayer];
options = trainingOptions('adam',...
'MaxEpochs',50,...
'MiniBatchSize',128,...
'SequenceLength',200);
这里有几个关键点:序列长度设200对应约5秒时间窗(数据采样率0.1Hz),dropout层防止过拟合效果明显。实际训练中发现初始学习率0.001时loss下降太慢,后来改成0.005后收敛更快。

测试集US06工况的结果让人有点惊喜,RMSE做到1.5%左右。特别是大电流波动时SOC跟踪效果不错:
pred_soc = predict(net, test_data);
figure;
plot(test_time, test_true_soc, 'b', test_time, pred_soc, 'r--');
legend('真实SOC','预测值');
title('US06工况测试结果');
不过发现在SOC接近50%时误差会短暂增大,可能和训练数据中中间区间的样本分布有关。后来在数据增强时增加了中间区间的数据扰动,效果有所改善。
改成GRU版本其实很简单,Matlab里直接把lstmLayer换成gruLayer就行。但要注意GRU的隐藏单元数要比LSTM多些,试下来128单元的GRU和64单元的LSTM效果相当:
% GRU版本网络结构
layers = [...
sequenceInputLayer(2)
gruLayer(256,'OutputMode','sequence')
dropoutLayer(0.3)
gruLayer(128)
fullyConnectedLayer(1)
regressionLayer];
实测GRU的训练速度比LSTM快30%左右,但长时记忆效果略逊一筹。个人更倾向在车载场景用GRU,毕竟实时性要求高,牺牲一点精度换速度值得。

最后附上数据处理代码中的关键片段,处理原始数据集时注意时间对齐问题:
% 数据预处理核心代码
function process_data(filename)
data = readtable(filename);
valid_idx = data.Voltage > 2.5 & data.Current ~= 0; % 剔除无效数据
processed = data(valid_idx, {'Time','Voltage','Current','SOC'});
% 时间戳转换为秒级间隔
time_diff = diff(processed.Time);
assert(all(abs(time_diff - 0.1) < 0.01), '采样间隔异常');
save([filename(1:end-4) '_processed.mat'], 'processed');
end
注意原始数据里有些充电阶段的零电流数据需要过滤掉。另外不同工况数据建议分开保存,训练时再合并,方便交叉验证。
这种时序建模方法最大的优势是能自动学习电压电流的时域特征,比传统卡尔曼滤波省去了建模过程。不过实际部署时需要考虑嵌入式设备的算力,可能需要做模型量化。最近在尝试用TensorFlow Lite做模型转换,有机会再分享经验。
更多推荐


所有评论(0)