第3章:数据采集与预处理
做微电网负荷预测,我有个很深的体会——数据质量决定了模型的天花板。你算法再牛,喂进去的是垃圾,出来的还是垃圾。这一章,咱们就聊聊数据从哪来、怎么洗、怎么喂。
3.1 数据来源:SCADA与AMI
微电网的数据源,说白了就两大系统:SCADA和AMI。我刚开始接触这个领域时,也傻傻分不清,后来踩过坑才明白它们的区别。
| 系统 | 采集对象 | 时间粒度 | 典型用途 |
|---|---|---|---|
| SCADA | 变电站、馈线、开关 | 秒级~分钟级 | 实时控制、保护 |
| AMI | 用户电表 | 15分钟~1小时 | 计费、负荷分析 |
SCADA(数据采集与监控系统)是微电网的"神经末梢"。它采集的是母线电压、馈线功率、开关状态这些实时数据。我在一个工业园区项目里,SCADA每5秒就传一次数据,量非常大,但噪声也多。
AMI(高级计量架构)则是用户侧的"账本"。它记录每家每户的用电量,粒度通常是15分钟或1小时。你想想看,做负荷预测时,SCADA的数据适合做超短期预测(未来几分钟到几小时),AMI的数据则适合做短期到中期预测(未来一天到一周)。
3.2 缺失值处理
数据缺失是家常便饭。通信中断、设备故障、人为误操作,原因太多了。我记得有一次,某台SCADA终端因为雷击坏了三天,那三天的数据全是空的。
处理缺失值,我一般按这个优先级来:
- 删除法——缺失比例小于5%且随机分布时,直接删掉整行。简单粗暴,但有效。
- 插值法——线性插值适合短时间缺失(比如连续缺2~3个点),多项式插值适合曲线变化平缓的场景。
- 前向/后向填充——用上一个或下一个有效值填充。适合负荷变化不大的时段,比如深夜。
- 模型预测填充——用KNN或回归模型预测缺失值。这是最后的手段,计算量大,但精度高。
# 我常用的缺失值处理代码(Python)
import pandas as pd
import numpy as np
# 读取数据
df = pd.read_csv('load_data.csv', index_col='timestamp', parse_dates=True)
# 检查缺失比例
missing_ratio = df.isnull().sum() / len(df)
print(f"缺失比例: {missing_ratio}")
# 缺失少于5% -> 直接删除
if missing_ratio.max() < 0.05:
df_clean = df.dropna()
# 否则用线性插值
else:
df_clean = df.interpolate(method='linear', limit_direction='both')
3.3 异常值检测
异常值比缺失值更隐蔽。它看起来有数值,但其实是错的。比如某天凌晨3点,负荷突然飙到正常值的5倍——这明显是传感器故障。
我常用的检测方法有三种:
- 3σ原则——假设数据服从正态分布,超出均值±3倍标准差的值视为异常。简单,但要求数据分布不能太偏。
- 箱线图法——用四分位数(Q1和Q3)计算IQR,超出Q1-1.5*IQR或Q3+1.5*IQR的值视为异常。对偏态分布更鲁棒。
- DBSCAN聚类——基于密度的聚类算法,把孤立点标为异常。适合多维数据,比如同时检测电压和电流的异常。
嗯,这里要注意:检测出异常值后,别急着删。先确认是不是真实事件。比如负荷突然飙升,可能是某个大设备启动了,那不是异常,是正常工况。
# 箱线图法检测异常值
Q1 = df['load'].quantile(0.25)
Q3 = df['load'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
anomalies = df[(df['load'] < lower_bound) | (df['load'] > upper_bound)]
print(f"检测到 {len(anomalies)} 个异常值")
3.4 数据归一化
归一化,说白了就是把不同量纲的数据拉到同一个尺度上。负荷数据可能是几千千瓦,温度数据是几十度,风速是个位数——不归一化,模型会"偏科"。
我常用的两种方法:
| 方法 | 公式 | 适用场景 |
|---|---|---|
| Min-Max归一化 | x' = (x - min) / (max - min) | 数据有明确边界,如负荷功率 |
| Z-score标准化 | x' = (x - μ) / σ | 数据分布未知,或有异常值 |
我个人习惯用Min-Max归一化做负荷预测。为什么?因为负荷数据通常有物理上限(比如变压器容量),归一化到[0,1]区间后,模型输出可以直接反算回实际值,解释性强。
# Min-Max归一化
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
# 只对训练集拟合
train_scaled = scaler.fit_transform(train_data)
# 用训练集的参数转换测试集
test_scaled = scaler.transform(test_data)
知识体系总览
下面这张图,是我梳理的数据采集与预处理全流程。你可以把它当作操作手册来用。
数据预处理这件事,看起来琐碎,但真不能马虎。我见过太多项目,模型选得再好,数据没洗干净,最后结果一塌糊涂。记住一句话:数据预处理花的时间,会在模型效果上十倍地还给你。
本章要点回顾:
- SCADA和AMI是两大数据源,时间粒度和用途不同
- 缺失值处理按"删除→插值→填充→预测"的优先级来
- 异常值检测后要人工确认,别盲目删除
- 归一化时训练集和测试集要分开处理