3. 数据采集与预处理:电池测试数据采集、数据清洗、缺失值处理、异常值检测、数据归一化与标准化
各位同学,咱们直接进入正题。数据采集与预处理,说白了就是给SOH模型「喂饭」。饭要是馊了,模型再牛也白搭。我在项目里见过太多人,模型调得飞起,结果数据一塌糊涂,最后全白干。今天咱们就把这顿饭怎么做,掰开揉碎了讲清楚。
核心观点:数据质量决定了SOH评估的天花板。算法再强,也救不了垃圾数据。
3.1 电池测试数据采集:你得知道要抓什么
采集数据前,先问自己三个问题:测什么?怎么测?测多细?
我个人习惯,先把关键参数列出来。电池测试,核心就这几样:
- 电压:单体电压、总电压。注意采样频率,我建议至少1Hz,动态工况要10Hz以上。
- 电流:充放电电流。正负号别搞反了,我吃过这个亏。
- 温度:电芯表面温度、环境温度。温度传感器位置很关键,贴歪了数据就偏了。
- 时间戳:这个容易被忽略。没有时间轴,数据就是死的。
- 容量:通过电流积分算出来的,但要注意累积误差。
采集设备方面,我推荐用高精度数据采集卡,至少16位ADC。别省这个钱,省下来的钱都会变成你加班调模型的时间。
我的小技巧:采集时同步记录环境温度。锂电池对温度极其敏感,同一块电池,25℃和0℃测出来的SOH能差好几个点。
3.2 数据清洗:把脏东西筛出去
数据拿到手,别急着建模。先看看数据长什么样。我一般会先做这几步:
- 去重:检查有没有完全重复的记录。有时候采集卡抽风,会连续记录两行一模一样的数据。
- 格式统一:时间戳统一成Unix时间戳或ISO格式。电压单位统一成伏特,别混着毫伏和伏特用。
- 范围检查:电压超出2.5V-4.3V(三元锂)的,基本是异常。电流超过电池规格书最大值的,也要标记出来。
我曾经接手过一个项目,对方给了三个月的数据,结果一查,时间戳有13种格式。你想想看,光解析时间就花了两天。所以,数据清洗这一步,省不了。
3.3 缺失值处理:别让空值毁了你的模型
数据缺失是常态。通讯中断、传感器故障、存储溢出,原因多了去了。处理缺失值,我一般按这个优先级来:
| 缺失比例 | 处理方法 | 适用场景 |
|---|---|---|
| < 5% | 线性插值 | 电压、电流等连续变化量 |
| 5% - 20% | 前向填充 / 后向填充 | 温度等变化缓慢的量 |
| > 20% | 直接删除该段数据 | 任何场景,别犹豫 |
举个例子,电压数据缺了3个点,前后值分别是3.7V和3.71V,线性插值算出来中间值3.705V,完全合理。但要是温度数据缺了半小时,就别插值了,直接删掉那一段。为什么?因为温度变化是非线性的,插值反而引入误差。
注意:千万别用均值填充来处理电池数据。电池的电压电流是动态变化的,用均值填充等于往数据里掺假。
3.4 异常值检测:揪出那些「不老实」的数据点
异常值检测,我常用的方法有三种:
- 3σ原则:数据服从正态分布时,超出均值±3倍标准差的值视为异常。简单粗暴,适合快速筛查。
- 箱线图法:用四分位数判断。Q1-1.5*IQR和Q3+1.5*IQR之外的点,就是异常。这个方法对分布没有要求,更通用。
- 局部异常因子(LOF):看一个点周围邻居的密度。密度明显低于邻居的,就是异常。适合复杂工况下的数据。
我记得有一次,一个客户的电池数据里,电压突然从3.8V跳到了5.2V。用3σ一查,果然异常。后来发现是采集卡的一个通道坏了。要是没做异常检测,模型学到的就是「电池能充到5.2V」,这不出大问题才怪。
3.5 数据归一化与标准化:让所有特征站在同一起跑线
归一化和标准化,很多人搞混。我简单说下区别:
- 归一化(Min-Max Scaling):把数据缩放到[0,1]区间。公式是 (x - min) / (max - min)。适合数据有明确边界的情况,比如电压范围已知。
- 标准化(Z-score Scaling):把数据变成均值为0、标准差为1的分布。公式是 (x - μ) / σ。适合数据分布未知或存在异常值的情况。
我个人习惯,做SOH评估时优先用标准化。为什么?因为电池数据里异常值多,归一化会被异常值拉偏。标准化对异常值的鲁棒性更好。
来看一段Python代码,很实用:
from sklearn.preprocessing import StandardScaler, MinMaxScaler
import numpy as np
# 假设你有一组电压数据
voltage = np.array([3.7, 3.8, 3.9, 4.0, 3.75, 3.85])
# 标准化
scaler_std = StandardScaler()
voltage_std = scaler_std.fit_transform(voltage.reshape(-1, 1))
# 归一化
scaler_mm = MinMaxScaler()
voltage_mm = scaler_mm.fit_transform(voltage.reshape(-1, 1))
print("标准化结果:", voltage_std.flatten())
print("归一化结果:", voltage_mm.flatten())
输出结果会告诉你,标准化后的数据有正有负,而归一化后的数据全在0到1之间。选哪个?看你的模型。像神经网络,一般用归一化;像SVM、KNN,标准化更合适。
避坑指南:我曾经犯过一个错——先做了异常值检测,再归一化。结果异常值被缩放到正常范围内,模型根本识别不出来。正确的顺序是:先处理异常值,再做归一化/标准化。
3.6 本章知识体系总览
下面这张图,是我自己总结的数据预处理流程。你照着这个走,基本不会出大错。
嗯,到这里,数据采集与预处理的核心内容就讲完了。你想想看,这些步骤看起来简单,但每一步都有坑。我当年刚入行时,光数据清洗就折腾了两个月。现在回头看,那些踩过的坑,都是宝贵的经验。
记住一句话:数据预处理花的时间,会在模型训练阶段加倍还给你。别急,慢慢来。