3、数据预处理与清洗:缺失值处理、异常值检测、数据去重、时间戳对齐、数据标准化
各位同学,咱们今天聊点实在的。
数据预处理,说白了就是给数据「洗澡」。你从现场拿回来的储能数据,十个里面有八个是脏的。我做了这么多年储能系统,见过太多「数据很漂亮,一跑模型就崩」的案例。嗯,这里要敲黑板——预处理做不好,后面所有算法都是白搭。
核心观点:数据预处理不是「可选项」,而是「必选项」。它占整个数据融合工作量的 60% 以上。
3.1 缺失值处理
先说说缺失值。储能系统的数据采集,经常因为传感器故障、通信中断、存储溢出等原因,导致某些时间点的数据没记下来。你想想看,一个 BMS 上报的电压数据,突然跳了个空值,这怎么处理?
我个人习惯把缺失值分成三类:
- 完全随机缺失:比如通信偶尔丢包,这种可以直接删掉或插值
- 随机缺失:比如某个传感器温度过高导致暂时失效,这种需要谨慎处理
- 非随机缺失:比如系统停机期间全部数据缺失,这种不能随便补
我在项目中遇到过最头疼的情况——某储能电站的 SOC 数据,每天凌晨 2 点到 4 点全部缺失。后来排查发现,是那个时段的定时校时任务把采集线程给阻塞了。这种缺失就不是随机事件,你如果用均值填充,模型会直接跑偏。
常用的处理方法,我列个表:
| 方法 | 适用场景 | 我的建议 |
|---|---|---|
| 删除法 | 缺失比例 < 5%,且随机缺失 | 简单粗暴,但别滥用 |
| 均值/中位数填充 | 数值型数据,波动不大 | 适合电压、温度等稳定指标 |
| 前向/后向填充 | 时间序列数据,变化缓慢 | SOC 用这个效果不错 |
| 插值法 | 数据有趋势性变化 | 线性插值最常用,别搞太复杂 |
| 模型预测填充 | 缺失比例高,且关系复杂 | 慎用,容易过拟合 |
小技巧:处理缺失值时,我建议先画个缺失值分布图。用热力图一看,哪些时间段、哪些变量缺失严重,一目了然。别上来就 fillna(),那是新手干的事。
3.2 异常值检测
异常值,说白了就是「看着不对劲」的数据。比如电池电压突然跳到 10V,或者 SOC 从 50% 瞬间变成 120%。这种数据不处理,模型会学出什么鬼东西来?
我常用的检测方法有几种:
- 3σ 原则:适合正态分布的数据,超出均值±3倍标准差就算异常
- 箱线图法:用 IQR(四分位距)来判定,不受极端值影响
- DBSCAN 聚类:适合多维数据的异常检测,我在做电池一致性分析时常用
- 孤立森林:高维数据效果好,但参数调起来有点烦
我曾经踩过一个坑——某项目用 3σ 原则检测电流异常,结果发现每天都有大量「异常值」。后来一查,是电池在充放电切换时,电流确实会瞬间跳变。这种「业务上的正常值」,算法却判成了异常。所以啊,异常值检测一定要结合业务场景,不能纯靠数学。
避坑指南:我曾经因为没做异常值检测,直接把数据喂给模型训练,结果模型收敛极慢,准确率还不到 60%。后来发现是某个传感器的噪声数据把模型带偏了。记住:异常值不处理,模型就是「垃圾进,垃圾出」。
3.3 数据去重
数据去重,听起来简单,做起来坑多。
储能系统的数据采集,经常因为重复上报、缓存重传、时间戳精度不够等原因,出现完全一样或高度相似的多条记录。你想想看,如果同一个时间点有两条一模一样的 SOC 数据,你留哪条?
我一般分两种情况处理:
- 完全重复:所有字段都一样,直接删掉一条,保留一条
- 部分重复:时间戳相同但其他字段不同,需要判断是合并还是保留最新
这里有个细节——时间戳精度。有些系统的采样周期是 1 秒,但时间戳只精确到秒,导致同一秒内有多条数据。这种情况不能简单去重,得先判断是不是正常的多点采样。
我在项目中遇到过最离谱的事——某 PCS 上报的数据,每 5 分钟重复一次,持续了整整一个月。后来发现是通信协议里的确认机制出了问题,数据发了两次。这种去重很简单,按时间戳去重就行。但如果是毫秒级的数据,就得小心了。
3.4 时间戳对齐
时间戳对齐,这是多源数据融合里最头疼的问题之一。
BMS 的数据是 100ms 上报一次,PCS 是 1s 上报一次,气象站是 5min 上报一次。这些数据的时间戳都不对齐,你怎么融合?
我常用的对齐策略:
- 降采样:把所有数据统一到最粗的时间粒度。比如都按 1 分钟对齐,简单但会丢失细节
- 升采样:把低频数据插值到高频。比如把气象数据从 5 分钟插值到 1 秒,但要注意别引入虚假信息
- 最近邻对齐:找时间上最接近的点进行匹配。适合实时性要求高的场景
我个人习惯用 pandas 的 resample 方法,配合 asfreq 或 interpolate。举个例子:
import pandas as pd
# 假设 bms_data 是 BMS 的原始数据,时间戳为索引
# 统一对齐到 1 秒
bms_aligned = bms_data.resample('1S').mean()
# 如果数据有缺失,用前向填充
bms_aligned = bms_data.resample('1S').ffill()
# 对于气象数据这种低频的,用线性插值
weather_aligned = weather_data.resample('1S').interpolate(method='linear')
经验之谈:时间戳对齐前,一定要先检查各个数据源的时间基准是否一致。我遇到过 BMS 用 UTC 时间,PCS 用本地时间,差了 8 个小时。这种问题不解决,对齐就是笑话。
3.5 数据标准化
最后说说标准化。不同传感器采集的数据,量纲不一样。电压是 V,电流是 A,温度是 ℃,SOC 是 %。这些数据直接放一起,数值大的变量会主导模型,数值小的变量就被淹没了。
常用的标准化方法:
- Min-Max 标准化:把数据缩放到 [0,1] 区间。适合数据分布比较均匀的情况
- Z-score 标准化:减去均值,除以标准差。适合数据近似正态分布的情况
- Robust 标准化:用中位数和 IQR,对异常值不敏感。我处理储能数据时最常用这个
为什么我偏爱 Robust 标准化?因为储能数据里经常有尖峰电流、瞬时电压波动,这些异常值如果用 Min-Max 标准化,会把正常数据压缩到很小的范围。用 Robust 的话,中位数和 IQR 不受极端值影响,效果稳定得多。
举个例子:
from sklearn.preprocessing import RobustScaler
import numpy as np
# 假设 data 是包含电压、电流、温度的三维数组
scaler = RobustScaler()
data_scaled = scaler.fit_transform(data)
# 标准化后的数据,中位数为 0,IQR 为 1
print(f"标准化后中位数: {np.median(data_scaled, axis=0)}")
print(f"标准化后 IQR: {np.percentile(data_scaled, 75, axis=0) - np.percentile(data_scaled, 25, axis=0)}")
重要提醒:标准化参数(均值、标准差、中位数等)一定要在训练集上计算,然后应用到验证集和测试集。千万别在整个数据集上算,否则会造成数据泄露,模型评估结果会虚高。
知识体系总览
下面这张图,是我梳理的数据预处理核心流程。你可以把它当成一个检查清单,每次做数据融合前,对着走一遍:
这张图看着简单,但每一步都有讲究。缺失值处理不好,后面的异常值检测就会误判;时间戳没对齐,标准化就是瞎搞。所以我的建议是:按顺序来,别跳步。
好了,数据预处理这块就聊到这儿。记住一句话:数据预处理做得好,后面建模没烦恼。你花 80% 的时间在预处理上,一点都不亏。