数据预处理:缺失值处理、异常值清洗、数据归一化与标准化
各位同行,咱们直接进入正题。数据预处理这步,说白了就是给模型「喂饭」之前,先把食材洗干净、切好。我见过太多项目,算法选得再好,数据一塌糊涂,结果全白搭。今天咱们就把这块硬骨头啃下来。
缺失值处理:别让「空」坑了你
储能系统的数据,缺失太常见了。传感器掉线、通信丢包、存储故障,哪个都能给你整出几个NaN。我刚开始做项目时,遇到缺失值就直接删行,后来发现删着删着数据就没了大半——尤其是高频采样数据,一秒钟几十个点,删起来心疼。
处理缺失值,我一般分三步走:
- 先诊断:看看缺失是随机的,还是系统性的。比如某个电池模组的电压总是缺失,那大概率是传感器坏了,不是数据偶然丢了。
- 再决策:缺失比例小于5%,直接删行问题不大。超过20%,就得想办法补了。
- 最后动手:补值方法我常用三种——
| 方法 | 适用场景 | 我的经验 |
|---|---|---|
| 前向填充 | 连续采样,短时间缺失 | SOC数据用这个最稳,电池状态不会突变 |
| 线性插值 | 温度、电压等缓变量 | 我曾经用这个补过一段BMS温度数据,效果比均值好很多 |
| 模型预测 | 关键参数,缺失模式复杂 | 慎用,容易引入偏差,我一般只用在最后验证阶段 |
小技巧:处理缺失值时,建议保留一个「是否缺失」的标记列。这样模型能学到「缺失」本身可能也是个信号。我在一个故障诊断项目里,就靠这个标记列发现了某个传感器老化的规律。
异常值清洗:把「野马」驯服
异常值,就是数据里的「野马」。储能系统里,常见的异常有几种:
- 物理极限异常:电压超过4.2V、电流超过额定值3倍——这明显是传感器抽风了
- 跳变异常:前一秒温度25°C,下一秒跳到80°C,然后又回来——通信干扰
- 趋势异常:SOC在充电时反而下降——数据逻辑错误
我常用的清洗方法,按粗暴程度排序:
- 3σ原则:简单粗暴,适合正态分布的数据。但储能数据很多不是正态的,慎用。
- IQR方法:用四分位距,不受极端值影响。我个人习惯用这个做第一道过滤。
- DBSCAN聚类:适合多维异常检测。比如同时看电压、电流、温度三个维度,离群点一目了然。
注意:别把「异常」和「故障」混为一谈。有些异常值恰恰是故障的前兆。我曾经因为清洗得太干净,把一个热失控的前期信号给洗掉了——那次教训让我学会了「先标记,后清洗,再回查」的流程。
# 我常用的IQR清洗代码
import numpy as np
def iqr_clean(data, column, factor=1.5):
Q1 = data[column].quantile(0.25)
Q3 = data[column].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - factor * IQR
upper = Q3 + factor * IQR
# 标记异常,不直接删除
data['异常标记'] = (data[column] < lower) | (data[column] > upper)
return data
数据归一化与标准化:让所有特征「平起平坐」
归一化和标准化,很多人搞混。我打个比方:
- 归一化:把所有数据压到[0,1]区间。就像把不同身高的人,都按比例缩放到同一个尺码。
- 标准化:让数据变成均值为0、标准差为1。就像把不同班级的考试成绩,都换算成标准分。
什么时候用哪个?我总结了个经验:
| 场景 | 推荐方法 | 为什么 |
|---|---|---|
| 神经网络、深度学习 | 标准化(Z-score) | 梯度下降更稳定,收敛快 |
| KNN、SVM等距离模型 | 归一化(Min-Max) | 避免大数值特征主导距离计算 |
| 树模型(随机森林、XGBoost) | 不需要 | 树模型基于分裂点,不受量纲影响 |
| 多源数据融合 | 标准化 | 不同BMS厂商的数据尺度不同,标准化后可比 |
核心原则:先拆分训练集和测试集,再用训练集的参数去归一化/标准化测试集。千万别把测试集的数据混进来算均值和方差——这是新手最容易犯的错,我当年也栽过。
# 标准化的正确姿势
from sklearn.preprocessing import StandardScaler
# 只fit训练集
scaler = StandardScaler()
train_scaled = scaler.fit_transform(X_train)
# 用同样的scaler transform测试集
test_scaled = scaler.transform(X_test)
知识体系总览
下面这张图,是我自己梳理的数据预处理流程。你想想看,从原始数据到干净可用的特征,中间要过多少道关?
嗯,流程就是这么个流程。但说实话,实际项目中很少能一步到位。我通常要来回迭代好几轮——先粗洗一遍,建模看看效果,发现不对劲再回头细调。数据预处理这事,七分技术,三分经验,慢慢磨吧。
我的习惯:每次预处理完,我都会保存一份「预处理日志」,记录每一步做了什么、删了多少数据、用了什么参数。这样出了问题能回溯,也方便跟团队沟通。你想想看,三个月后回头查一个模型,要是没有日志,那真是抓瞎。