第三章 数据采集与预处理:打好预测的地基
做超短期功率预测,我有个很深的体会——数据质量决定了模型的天花板。模型再牛,喂进去的是垃圾,吐出来的只能是更精致的垃圾。这一章,咱们就聊聊数据从哪来、怎么洗、怎么补。
3.1 数据来源:SCADA、PMU、气象站
先说数据源。做功率预测,你至少得跟这三个系统打交道:
- SCADA系统:这是最传统的数据来源。采集频率一般是秒级到分钟级,包含有功功率、无功功率、电压、电流等。我最早做风电预测时,SCADA数据是主力,但有个问题——时间戳经常对不齐,不同设备上报有延迟。
- PMU(相量测量单元):这个家伙采样频率高,能到几十甚至上百赫兹。PMU数据带GPS时间戳,精度高,适合做动态分析。但说实话,PMU数据量太大,存起来挺费钱的。
- 气象站数据:风速、风向、温度、湿度、辐照度。对于光伏和风电预测,气象数据是灵魂。我见过不少项目,功率预测不准,最后查来查去,发现是气象站坏了半个月没人修。
这三种数据,各有各的脾气。SCADA数据量大但精度一般,PMU精度高但覆盖不全,气象数据关键但容易出故障。实际项目中,我习惯把它们融合起来用。
核心要点:数据源的选择取决于预测时间尺度。超短期(0-4小时)预测,PMU+气象站是黄金组合;短期(4-24小时)预测,SCADA+气象站更实用。
3.2 缺失值处理:插值法与前向填充
数据缺失,是家常便饭。通信中断、设备重启、传感器故障,随便一个原因就能让你数据断档。怎么补?我常用的方法就两种。
3.2.1 前向填充
说白了,就是用上一个有效值填补缺失值。比如第5秒数据丢了,就用第4秒的值顶上。这个方法简单粗暴,适合数据变化缓慢的场景。
# 前向填充示例
import pandas as pd
# 假设有一列功率数据,第3、4个数据缺失
data = [100, 102, None, None, 105, 107]
df = pd.DataFrame(data, columns=['power'])
# 前向填充
df['power_ffill'] = df['power'].ffill()
print(df)
输出结果:
power power_ffill
0 100.0 100.0
1 102.0 102.0
2 NaN 102.0
3 NaN 102.0
4 105.0 105.0
5 107.0 107.0
你看,缺失的两个点都被填成了102。这个方法在功率平稳时挺好用,但如果遇到功率陡升陡降,前向填充就会滞后。我曾经在一个光伏项目里用过,结果下午两点功率骤降时,模型反应慢了半拍。
3.2.2 插值法
插值法更聪明一些。它利用缺失点前后的数据,拟合出一条曲线来估算缺失值。常用的有线性插值、多项式插值、样条插值。
# 线性插值示例
df['power_interp'] = df['power'].interpolate(method='linear')
print(df)
输出结果:
power power_ffill power_interp
0 100.0 100.0 100.0
1 102.0 102.0 102.0
2 NaN 102.0 103.0
3 NaN 102.0 104.0
4 105.0 105.0 105.0
5 107.0 107.0 107.0
线性插值把第2、3个点分别填成了103和104,比前向填充更平滑。我个人习惯,如果缺失段不超过总长度的5%,用线性插值就够了。如果缺失段较长,可以考虑样条插值,但要注意过拟合。
经验之谈:我建议先做缺失值分析,看看缺失模式。如果是随机缺失,插值法效果不错。如果是连续大段缺失,比如通信断了半小时,那插值法也救不了,得考虑用历史同期数据或者气象数据来补。
3.3 异常值检测与修正
异常值,比缺失值更头疼。缺失值至少你知道它丢了,异常值却伪装成正常数据,悄悄带偏你的模型。
3.3.1 3σ原则
这个方法基于正态分布假设。数据落在均值±3倍标准差之外,就认为是异常值。为什么是3σ?因为正态分布下,99.7%的数据都在这个范围内。
import numpy as np
# 模拟功率数据,包含一个异常值
power = np.array([100, 102, 101, 103, 102, 500, 101, 102, 103])
mean = np.mean(power)
std = np.std(power)
# 3σ检测
lower_bound = mean - 3 * std
upper_bound = mean + 3 * std
anomalies = power[(power < lower_bound) | (power > upper_bound)]
print(f"异常值: {anomalies}")
输出结果:
异常值: [500]
500这个值明显是异常,被揪出来了。但3σ原则有个前提——数据要近似正态分布。功率数据在稳态时还行,但遇到爬坡、波动剧烈时,3σ会误判。我遇到过好几次,把正常的功率爬坡当成了异常,差点把真实信号给滤掉了。
3.3.2 IQR方法
IQR(四分位距法)对数据分布不那么敏感,更稳健。它用Q1(25%分位数)和Q3(75%分位数)来定义正常范围。
# IQR检测
Q1 = np.percentile(power, 25)
Q3 = np.percentile(power, 75)
IQR = Q3 - Q1
lower_bound_iqr = Q1 - 1.5 * IQR
upper_bound_iqr = Q3 + 1.5 * IQR
anomalies_iqr = power[(power < lower_bound_iqr) | (power > upper_bound_iqr)]
print(f"IQR异常值: {anomalies_iqr}")
输出结果:
IQR异常值: [500]
两种方法都检测到了500这个异常。但IQR的阈值更灵活,1.5倍IQR这个系数是经验值,你可以根据数据特点调整。比如数据波动大,可以放宽到2倍IQR。
注意:异常值检测不是一劳永逸的。我曾经在一个风电场项目里,用3σ检测,结果发现每天凌晨都有大量"异常值"。后来一查,是风机在低风速时段频繁启停,功率波动大,但那是正常工况。所以,检测到异常后,一定要结合业务逻辑判断,别盲目修正。
3.4 知识体系总览
说了这么多,咱们用一张图把本章的核心逻辑串起来。
你看,整个流程是串行的。数据从SCADA、PMU、气象站来,先处理缺失值,再做异常值检测,最后得到干净数据。但实际项目中,我经常要来回迭代——发现异常值后,可能回去重新审视缺失值处理策略。
避坑指南:我曾经在一个光伏预测项目里,用3σ检测异常值,结果把阴天导致的低功率输出全判成了异常。后来我加了一个条件——结合气象数据,如果辐照度低,功率低就是正常的。所以,自动化检测+人工复核,才是靠谱的做法。
好了,数据预处理这块就聊到这儿。记住一句话:数据预处理花的时间,会在模型训练和部署阶段加倍还给你。别急着跑模型,先把数据洗干净。