简介NASA锂电池老化实验数据集面向电池寿命预测、SOC估计与健康管理PHM研究场景适合从事电池退化建模、剩余使用寿命预测和充放电策略分析的研究者与工程师。数据源自NASA Ames预测卓越中心完整记录了锂离子电池在不同温度下的充放电循环实验并将阻抗作为电池老化的损伤判据。压缩包共35个文件以33个MAT数据文件为主辅以1个M脚本用于容量计算和1个TXT说明文件总体积174.12MB可直接在MATLAB中加载使用。目前已有4306人学习下载。借助这套数据可提取电压、电流、容量和阻抗等多维特征开展SOC估计、SOH评估及剩余寿命预测实验也可作为电池管理算法验证和PHM方法研究的标准测试基准。 做电池健康管理、寿命预测方向的研究一定会绕不开一份数据NASA艾姆斯研究中心的电池实验数据集。我最早接触它是在做锂离子电池剩余寿命RUL预测的硕士课题时当时在公开数据里翻了一圈最后几乎所有论文的对比实验都用这份数据因为它的工况定义清晰、老化轨迹完整而且免费开放。后来做BMS算法评估、储能系统健康状态SOH估计它也一直是我用来验证pipeline的首选数据集。这篇博文我想把这份数据集的来龙去脉、文件结构、隐藏细节和建模实操完整讲一遍。不管你是刚开始接触电池数据挖掘的学生还是已经在做电池管理系统算法开发的工程师只要打算用NASA这份数据做SOH估计、RUL预测或者迁移学习实验这篇文章都能帮你少踩不少坑。1. 实验台背后的设计四块电池与三个老化变量1.1 四块18650电池与三种测试动作NASA这个数据集来自艾姆斯研究中心的预测卓越中心PCoE用的实验对象是四块商用18650锂离子电池编号分别是B0005、B0006、B0007和B0018。电池标称容量2Ah标称电压3.6V左右。整个实验过程中每块电池反复执行三种动作充电、放电、阻抗测量。充电采用的是标准的恒流恒压CC-CV策略先用1.5A恒流把电池充到4.2V然后转为4.2V恒压直到充电电流降到20mA才停止。放电则是2A恒流放电每块电池的截止电压不同这是整个实验里最重要的变量电池编号放电截止电压实验定位B00052.7V浅放对照组B00062.5V中等放电深度B00072.2V深放组B00182.5V与B0006截止电压相同可做重复性对照每完成一次完整的充放电循环实验系统会插入一次阻抗测量用扫频的方式记录电池在不同频率下的交流阻抗响应。所以每个循环的数据文件里其实包含了充电、放电、阻抗三部分记录这三部分对应了电池老化过程中不同维度信息的快照。1.2 为什么放电截止电压是核心实验变量很多人第一次看这份数据会把注意力放在充电策略上但真正控制老化速度的是放电深度。放电截止电压越低意味着每次循环里从正负极材料中脱嵌的锂离子越多电极材料的体积应变越大SEI膜的破裂和重构也越频繁容量衰减自然更快。实验里1.5A充、2A放的设计也很有意思。按2Ah标称容量算2A放电正好是1C倍率既不会因为倍率过高导致电池瞬间过热又能把一次循环压缩在合理时间内。NASA选的这个工况介于常规使用和加速老化之间所以数据既不像手机电池那种浅充浅放模式那么温和也不像纯高温高倍率加速老化那样极端非常适合用来验证寿命预测算法。1.3 阻抗测量是穿插在循环里的“体检报告”阻抗测量的物理意义值得多说两句。锂电池的老化不光是容量下降内部电化学过程也在悄悄变化。通过电化学阻抗谱可以分离出电解液电阻、SEI膜电阻、电荷转移电阻等不同环节的贡献。数据文件中对应的字段包括实部阻抗、虚部阻抗以及计算出的Re、Rct等参数。但使用阻抗数据时要有清醒认识它的采样频率很低每个循环只在充放电间隙测一轮时间分辨率远低于电压电流数据。它更适合作为描述电池内部状态缓慢演变的辅助特征而不是用来做逐秒级别的动态预测。2. 拆开MAT文件B0005里每一层数据是什么2.1 用Python加载嵌套的mat结构NASA在官网上提供的是MAT格式文件用MATLAB的load可以直接读。国内更多人用Pythonscipy.io.loadmat也能读但读出来的是嵌套的numpy结构数组很多新手第一次接触会懵。我先给出一个可以跑的加载代码import scipy.io import numpy as np mat scipy.io.loadmat(B0005.mat) battery mat[B0005] # battery 是一个 1x1 的结构通过 cycle 字段拿到循环记录 cycle battery[0, 0][cycle] print(type(cycle), cycle.shape) # 遍历所有循环统计不同类型记录的数量 type_counts {} for i in range(cycle.shape[1]): t cycle[0, i][type][0, 0] type_counts[t] type_counts.get(t, 0) 1 print(type_counts)运行后你会发现B0005里总共包含大概168个循环其中大部分是完整的充放电循环夹在中间的还有一些单独标记的阻抗测试。charge、discharge、impedance三种类型都可以在这里区分出来。2.2 充放电状态混叠按type分流是第一步这份数据文件里每个cycle节点下既有充电数据又有放电数据。如果你不去看type字段直接把所有数据遍历并画图或者直接塞给模型结果肯定是灾难性的因为充电的电压在上升、放电的电压在下降电流方向也相反混在一起做序列建模时模型会学到完全错误的规律。所以拿到数据的第一步永远是分流。用上一节的type统计结果把几类数据分别提取出来。放电数据中还有一个Capacity字段代表这个循环放电阶段累计放出的容量这个值就是后续计算SOH和RUL的最基础标签。2.3 Capacity字段其实是重复值别被坑了这里有个小坑放电数据中每一行采样点都带一个Capacity字段但Capacity并不是该采样时刻的实时容量而是整个循环结束后累计的容量值被赋值到了该循环的每一行上。也就是说你随便取放电阶段数据的任意一行读到的Capacity都是一样的。正确的用法是取第一个放电采样点的Capacity或者直接取该循环记录里Capacity数组的第一个元素。如果用pandas把整个放电段读成DataFrame后直接对Capacity求平均值倒也不会出错但会白白浪费算力而且如果你在做增量计算很容易在后面的时序建模中引入重复值泄漏。3. 三个容易忽略的数据细节直接影响预测误差3.1 采样间隔不齐别把电池数据当成等间隔时序NASA数据虽然记录频率看起来是固定的但仔细检查会发现充电阶段和放电阶段的采样间隔并不完全一致。充电记录通常更密一些而且不同循环之间由于充电时间随老化缩短实际采到的数据点数也会变少。这带来一个实际问题如果你直接把原始电压序列按时间步喂给LSTM或Transformer不同样本的序列长度可能不一致需要padding或者截断更麻烦的是老化的信息恰恰体现在序列长度变短这个现象里如果padding截断做得不好等于把最核心的老化特征抹掉了一部分。我的建议是做特征提取时优先用循环编号作为序列索引把每个循环内的原始曲线先压缩成标量特征比如恒流充电时间、等压升时间差、容量、温度峰值等。这样建模时用的是固定长度特征向量完全绕开采样间隔不齐的问题。3.2 SOH口径不统一你的结果和论文没法比SOH的定义在不同文献里差异很大。有人用当前容量除以初始额定容量有人用当前容量除以第一个完整循环的实测容量还有人用内阻变化来定义。NASA电池的额定容量是2Ah但B0005实测第一个完整循环的放电容量大约在1.85Ah到1.97Ah之间和标称值差了约7%。如果A论文用2Ah当分母B论文用第一个循环实测容量当分母同一个电池同一时刻的SOH数值会差出好幾個百分点结论自然不可比。我的经验是无论用哪个口径都要在论文或实验报告里写明分母的具体值并且建议用首个完整循环的实测容量作为基准因为它更接近电池当下的真实可用容量。3.3 温度数据是表面温度不是内部温度数据文件里的Temperature_measured字段来自贴在电池表面的热电偶不是电池内部温度。这带来两个后果第一温度曲线相比内部电化学产热会有明显滞后快速放电时表面温度上升比内部慢第二在循环的后半段温度开始下降并不意味着电池不再产热可能只是环境热平衡在起作用。所以如果你直接用温度数据做RUL预测的输入特征要意识到它和容量衰减之间不是简单的因果关系更像是一个相关指标。温度可以作为辅助特征但不要指望它单独给出对老化机理的精确解释。4. 从容量曲线到RUL一个能直接跑的建模基线4.1 先把RUL预测问题定义清楚以B0005为例我们可以把问题定为已知前40个完整循环的充放电数据预测电池容量首次低于1.4Ah的循环序号。1.4Ah对应标称容量的70%这是一个比较常见的退役阈值。不同的电池阈值不同比如B0007由于设计上就偏深放容量衰减更快同一个阈值对应的循环数会明显少于B0005。按这个定义RUL的标签是离散值比如“第147个循环达到退役条件”。为了验证算法效果通常用前40个循环的数据训练然后预测后续所有循环的容量或RUL再和真实曲线对比。4.2 从恒流充电曲线提取等压升时间差特征电池老化后最直观的变化是恒流充电阶段电压上升更快因为能容纳的锂离子变少了。为了把这个现象量化为特征可以用“等压升时间差”方法取恒流充电段的电压与时间序列从3.0V开始每隔0.1V记录一次对应的时间点计算相邻电压档位之间的时间长度。这一系列时间差构成了一个特征向量。这个特征的效果相当好因为它是dQ/dV的间接体现而dQ/dV曲线峰值的变化能直接反映电池容量衰减。我建议把整个恒流段的等压升时间差向量作为特征序列输入模型而不是只用某个单一时间点。示例代码如下def extract_delta_t(voltage, time, v_start3.0, v_end4.2, v_step0.1): levels np.arange(v_start, v_end 1e-6, v_step) t_at_level [] for v in levels: idx np.where(voltage v)[0] t_at_level.append(time[idx[0]] if len(idx) 0 else np.nan) t_at_level np.array(t_at_level) delta_t np.diff(t_at_level) return delta_t, levels4.3 高斯过程回归小样本预测的稳妥起点在只有几十个循环、特征维度又不高的情况下复杂深度学习模型的收益其实很有限。高斯过程回归GPR是一个非常合适的基线样本量小、非线性能拟合、还能给出预测的不确定性区间。下面是一个基于scikit-learn的实现框架from sklearn.gaussian_process import GaussianProcessRegressor from sklearn.gaussian_process.kernels import ConstantKernel, RBF, WhiteKernel kernel ConstantKernel(1.0) * RBF(length_scale10.0) WhiteKernel(noise_level1.0) gpr GaussianProcessRegressor(kernelkernel, alpha1e-6, normalize_yTrue) gpr.fit(X_train, y_train) y_pred, y_std gpr.predict(X_test, return_stdTrue)输入X_train可以设计成前N个循环的等压升时间差特征y_train是这些循环的容量值训练完成后用未来的时间点预测未来的容量直到预测容量低于退役阈值此时的循环序号就是RUL。评估指标推荐RMSE和MAPE同时要画出预测曲线并带上置信区间。这里我必须强调单一电池上的表现好不叫好。一定要做跨电池验证比如用B0006、B0007、B0018三块电池的数据训练在B0005上测试。因为电池之间随机性很大一个模型只在B0005上拟合出了衰减曲线形状换一块电池可能就废了。跨电池的RUL预测才是真正检验算法泛化能力的战场。5. 跳出标准用法四块电池的迁移学习与随机容量预测5.1 随机容量预测和RUL不同的一种任务设定传统RUL预测要求模型按时间顺序外推但实际BMS场景里用户往往是在某个不确定的时刻询问“这块电池现在还有多少容量”这更像一个回归问题而不是序列预测问题。最近一些研究把这种设定叫做“随机容量预测”Random Capacity Prediction。具体做法给定某个循环的充电曲线片段不管它前面经历了多少个循环直接回归预测这个循环的放电容量。这时候不需要建模完整的退化轨迹只需要从充电曲线提取健康特征然后做监督回归。用NASA数据做这个任务时可以把四块电池的所有循环混合在一起每一行样本是“某个循环的等压升时间差特征 当前容量标签”。训练一个GPR或MLP四块电池的数据一起用效果往往比单块电池单独训练更好因为模型见过了更多老化形态。5.2 迁移学习怎么划分源域和目标域在四块电池构成的迁移学习实验里有一个划分策略我比较推荐用B0006、B0007、B0018作为源域B0005作为目标域。原因是B0005的放电截止电压最高退化最慢数据分布和其他三块的差异最明显能在目标域上做更严格的泛化检验。迁移学习里有一个非常容易被忽视的细节归一化参数只能用源域数据计算。很多人习惯把全部数据放在一起做标准化再划分训练测试集这在迁移场景里属于信息泄漏会让指标虚高。正确做法是先从源域拟合归一化参数再把这个参数应用在目标域上。5.3 和CALCE、Oxford等其他公开数据集怎么配合NASA数据集虽然经典但四块电池的样本量远不足以支撑大规模深度学习实验而且充放电策略比较单一覆盖不了多倍率、多温度的实际工况。做研究时可以把CALCE、Oxford等高校发布的电池老化数据集一起纳入对比。不同数据集的循环策略、环境温度、电池型号都不一样正好用来检验算法的工况泛化能力。我个人的流程是先在NASA数据上把特征提取、模型验证、指标评估这条pipeline跑通再在自己的私有数据或补充数据集上做二次验证。这样调试成本最低因为NASA数据社区资料多你踩过的坑几乎都有前人踩过排查起来方便。最后分享一个我在实际项目中常用的习惯拿到B0005.mat之后先把充放电数据转成CSV或Parquet格式存一份每一行是一个循环内的采样点再加一列cycle标号。这样后续无论是用pandas分析还是分发给团队其他人都比每次从嵌套mat里去取数方便得多。NASA这份数据集最大的价值不在于它有多大规模而在于它把“电池老化”这个复杂过程用清晰、完整的方式记录下来了配合正确的使用姿势它足够支撑你完成从入门到进阶的绝大多数电池算法实验。本文还有配套的精品资源点击获取