3. 数据采集与预处理:电池测试数据采集与清洗
各位同学,大家好。今天我们来聊聊数据采集与预处理。说实话,这一步在SOC估算里,比算法本身还重要。我见过太多项目,算法模型调得天花乱坠,结果数据一塌糊涂,最后全白费。所以,咱们得把地基打牢。
3.1 电池测试数据采集:电流、电压、温度
电池测试数据,说白了就是三个核心物理量:电流、电压、温度。这三个量,一个都不能少。
- 电流:反映电池的充放电速率。单位是安培(A)。正电流表示充电,负电流表示放电。我个人习惯用高精度分流器来采集,精度能到0.1%以上。
- 电压:单体电压和总电压都要采。单体电压能看出电池的一致性,总电压用于整体SOC估算。采样频率建议至少1Hz,动态工况下要10Hz以上。
- 温度:电池性能对温度极其敏感。我建议在电池模组的正负极、中心位置都布置温度传感器。NTC热敏电阻是常用方案,便宜且可靠。
重要提醒:数据采集的同步性非常关键。电流、电压、温度必须同一时间戳记录。否则,你算出来的SOC会偏差很大。我在项目中遇到过,因为采集板卡时钟不同步,导致SOC误差超过5%。后来加了硬件同步信号才解决。
3.2 数据清洗:异常值处理与缺失值填充
采集到的原始数据,就像刚挖出来的矿石,杂质很多。数据清洗就是把这些杂质去掉。
3.2.1 异常值处理
异常值怎么判断?我常用的方法有三种:
- 3σ原则:假设数据服从正态分布,超出均值±3倍标准差的值视为异常。适合静态工况。
- 箱线图法:用四分位数(Q1和Q3)计算IQR,超出Q1-1.5*IQR或Q3+1.5*IQR的值视为异常。适合非正态分布数据。
- 物理约束法:根据电池特性设定合理范围。比如,磷酸铁锂电池单体电压不会超过3.65V,低于2.0V就是异常。这个方法最可靠,我强烈推荐。
我的经验:我曾经处理过一批数据,电压值突然跳变到5V。用3σ法没检测出来,因为整体数据量大。后来用物理约束法,直接定位到传感器故障。所以,物理约束法永远是第一道防线。
3.2.2 缺失值填充
数据缺失的原因很多:通信丢包、传感器掉线、存储故障。处理方式有几种:
- 删除法:如果缺失比例小于5%,直接删除该行数据。简单粗暴,但有效。
- 均值/中位数填充:用前后数据的均值或中位数填充。适合短时间缺失。
- 插值法:线性插值或样条插值。我个人习惯用线性插值,计算量小,效果也不错。
- 前向填充:用上一个有效值填充。适合温度这种变化缓慢的量。
注意:缺失值填充不能过度。如果连续缺失超过10个点,我建议直接标记为无效数据段,而不是强行填充。否则会引入虚假信息,影响模型训练。
3.3 数据归一化与标准化
为什么要做归一化?你想想看,电流的范围可能是-200A到200A,电压是2.5V到4.2V,温度是-20℃到60℃。这些量纲完全不同。如果不处理,机器学习模型会天然偏向数值大的特征。
常用的方法有两种:
| 方法 | 公式 | 适用场景 |
|---|---|---|
| Min-Max归一化 | x' = (x - min) / (max - min) | 数据分布有明确边界,如电压、温度 |
| Z-score标准化 | x' = (x - μ) / σ | 数据分布近似正态,如电流波动 |
我个人习惯:电压和温度用Min-Max归一化,电流用Z-score标准化。为什么?因为电压和温度的范围相对固定,而电流的波动范围变化很大,用Z-score能更好地保留分布信息。
# Python代码示例:归一化与标准化
import numpy as np
from sklearn.preprocessing import MinMaxScaler, StandardScaler
# 假设data是numpy数组,列顺序为[电流, 电压, 温度]
data = np.array([[10, 3.2, 25],
[20, 3.3, 26],
[15, 3.1, 24]])
# 电压和温度用Min-Max归一化
scaler_minmax = MinMaxScaler()
data[:, 1:3] = scaler_minmax.fit_transform(data[:, 1:3])
# 电流用Z-score标准化
scaler_zscore = StandardScaler()
data[:, 0:1] = scaler_zscore.fit_transform(data[:, 0:1])
print(data)
3.4 特征工程初步:差分与滑动窗口
原始数据直接喂给模型,效果往往不好。我们需要构造更有意义的特征。这里介绍两个最基础的操作:差分和滑动窗口。
3.4.1 差分
差分就是计算相邻时间点的变化量。比如,电流差分能反映电流的变化率,电压差分能反映电压的波动。公式很简单:
Δx(t) = x(t) - x(t-1)
为什么要做差分?因为电池的SOC变化不仅取决于当前状态,还取决于变化趋势。比如,电流突然增大,说明车辆在急加速,SOC会快速下降。差分特征能捕捉这种动态信息。
避坑指南:我曾经在项目中只用了原始特征,模型精度一直上不去。后来加入电流差分和电压差分,RMSE直接降低了15%。所以,差分特征几乎是必加的。
3.4.2 滑动窗口
滑动窗口就是取一段时间内的统计量。比如,过去5秒的平均电流、过去10秒的电压标准差。这些统计量能反映电池的短期历史行为。
常用的滑动窗口特征:
- 均值:反映趋势
- 标准差:反映波动程度
- 最大值/最小值:反映极端情况
- 积分:反映累计电量(Ah)
# Python代码示例:滑动窗口特征
import pandas as pd
# 假设df是DataFrame,包含'current'列
df['current_mean_5s'] = df['current'].rolling(window=5).mean()
df['current_std_5s'] = df['current'].rolling(window=5).std()
df['current_max_10s'] = df['current'].rolling(window=10).max()
注意:滑动窗口的窗口大小需要根据采样频率和工况来定。采样频率1Hz时,窗口5-10秒比较合适。采样频率10Hz时,窗口可以扩大到50-100个点。窗口太小,噪声大;窗口太大,反应迟钝。嗯,这里需要根据实际数据调试。
好了,数据采集与预处理就讲到这里。下一章我们会正式进入机器学习模型的世界。记住,数据质量决定了模型的上限。把这一步做好,后面的路会顺畅很多。