数据采集与预处理:电池充放电数据采集、数据清洗、异常值处理、数据归一化与标准化
做SOH算法这些年,我最大的体会就是:数据质量决定了算法上限。你模型再花哨,喂进去一堆脏数据,结果也是白搭。今天咱们就聊聊数据采集与预处理这档子事。
电池充放电数据采集
数据采集是第一步,也是最容易被忽视的一步。我个人习惯把采集分成两个层面:实验室级和实车级。
实验室数据,说白了就是你在恒温箱里,用充放电柜跑出来的。电压、电流、温度、容量,一条条记录得清清楚楚。我刚开始做的时候,总觉得实验室数据够干净,后来发现——太干净了反而不好。为什么?因为实车数据根本不是这样。
实车数据就复杂多了。你想想看,车辆启动、急加速、能量回收、停车休眠……各种工况混在一起。采样频率也不固定,有的CAN总线1秒传一次,有的10秒才传一次。嗯,这里要注意:采样频率不一致,后期对齐很麻烦。
核心采集参数:
- 电压(单体/总压)
- 电流(充放电方向)
- 温度(电芯/模组/环境)
- 时间戳(精确到毫秒)
- 累计充放电容量(Ah)
我在项目中遇到过一件事:某款车的数据里,电流值偶尔会跳成负数。查了半天,发现是霍尔传感器零点漂移了。所以啊,采集端加个校验逻辑,能省后面很多事。
数据清洗
数据拿到手,第一件事不是建模,是洗数据。我见过太多人上来就跑算法,结果跑出来一堆垃圾。
清洗什么?
- 重复数据:同一时间戳出现多条记录,保留第一条或取平均
- 缺失数据:时间戳断了,用插值还是直接删?看情况
- 无效数据:比如电压为0、电流为0但SOC在变化——这明显不合理
举个例子,你拿到一段充电数据,电压从3.0V到4.2V,中间突然跳了个3.8V又跳回3.1V。这种大概率是通信丢包或者传感器误报。我一般用滑动窗口滤波来处理:
def sliding_window_filter(data, window_size=5, threshold=0.1):
filtered = []
for i in range(len(data)):
if i < window_size or i >= len(data) - window_size:
filtered.append(data[i])
continue
window = data[i-window_size:i+window_size+1]
median = np.median(window)
if abs(data[i] - median) > threshold:
filtered.append(median) # 用中位数替换
else:
filtered.append(data[i])
return filtered
小技巧:清洗时别太激进。我曾经一刀切删了太多数据,导致后面训练集不够用。建议先可视化看看分布,再决定清洗策略。
异常值处理
异常值,说白了就是那些「看着就不对」的数据。但怎么定义「不对」?
常见异常类型:
| 异常类型 | 示例 | 处理方法 |
|---|---|---|
| 物理限值超限 | 电压>5V(磷酸铁锂单体) | 直接剔除 |
| 跳变异常 | 1秒内电压变化>0.5V | 中值滤波或插值 |
| 趋势异常 | 充电时电压持续下降 | 检查传感器/剔除片段 |
| 静态异常 | 长时间电压纹丝不动 | 可能是休眠数据,保留但标记 |
我记得有一次,某批电池的SOH估算总是偏低。排查了很久,发现是数据里混入了一些「充电未满」的片段。这些片段电压到了4.1V就停了,但实际还没充满。算法误以为容量衰减了。后来我加了个充电截止条件判断:只有电压达到4.2V且电流小于C/20的片段才用来算容量。
避坑指南:我曾经把「温度异常」直接当异常值删了,结果发现冬天低温数据全没了,模型在低温工况下完全失效。后来我改成:异常值先标记,再单独分析,不轻易删除。
数据归一化与标准化
这一步很多人觉得简单,不就是把数据缩放到0~1嘛。其实没那么简单。
归一化(Min-Max Scaling):
def min_max_scaler(data, min_val, max_val):
return (data - min_val) / (max_val - min_val)
适合电压、温度这种有明确物理边界的参数。比如电压3.0V~4.2V,归一化后就是0~1。但要注意:如果新数据超出了训练时的范围,归一化会失效。我遇到过实车电压跑到2.8V的情况,归一化后变成了负数,模型直接懵了。
标准化(Z-score Normalization):
def z_score_scaler(data, mean, std):
return (data - mean) / std
适合电流、功率这种分布不确定的参数。标准化后均值为0,方差为1。我个人习惯对电流做标准化,因为电流正负都有,归一化反而不方便。
怎么选?
- 有明确上下界的参数(电压、温度)→ 归一化
- 分布未知或存在离群值的参数(电流、功率)→ 标准化
- 同一批数据里,训练集和测试集要用相同的scaler,别各算各的
我的经验:归一化和标准化不是二选一。有时候我会对电压做归一化,对电流做标准化,对容量做对数变换。关键是理解你的数据分布,而不是套公式。
你想想看,如果电压和电流的量纲差了几十倍,不归一化的话,模型会天然偏向数值大的特征。说白了,预处理做得好,模型训练事半功倍。
嗯,数据采集与预处理就聊到这儿。下一章咱们聊聊特征工程——怎么从这些数据里挖出对SOH有用的信息。