第四节:数据采集与预处理——风机SCADA数据、振动数据、气象数据的清洗与特征工程
各位同事,今天我们来聊聊数据预处理。说实话,这活儿看着不起眼,但在我多年的风电运维经验里,数据清洗和特征工程往往决定了模型的上限。你模型再牛,喂进去的是垃圾,出来的只能是垃圾。这个道理,我在好几个项目里都吃过亏才真正明白。
4.1 三类核心数据源的特点
我们先捋清楚要处理哪几类数据。风机运维中,最常见的就是这三兄弟:
- SCADA数据:每10分钟一条记录,包含风速、功率、转速、温度等几十个参数。数据量大,但采样频率低。
- 振动数据:高频采样,每秒几千甚至上万次。数据量巨大,但能捕捉到齿轮箱、轴承的早期故障特征。
- 气象数据:风速、风向、温度、湿度、气压等。通常来自机舱上的气象站,或者第三方气象服务。
这三类数据,采样频率不同、单位不同、质量也不同。你想想看,要把它们揉在一起做智能派单,第一步就是对齐和清洗。
核心原则:数据清洗不是越干净越好,而是保留对故障诊断和派单决策有用的信息。过度清洗会丢失故障特征。
4.2 SCADA数据清洗——我踩过的坑最多
SCADA数据看起来规整,其实暗坑不少。我个人习惯,拿到SCADA数据先做三件事:
- 缺失值处理:SCADA偶尔会丢包,尤其是通讯不稳定的风场。我一般用前向填充,最多填充3个时间点。超过3个连续缺失,直接标记为无效时段。
- 异常值剔除:风速超过切出风速还显示发电?功率为负值?温度传感器显示-999?这些明显不合理的数据,直接删掉。
- 时间戳对齐:不同风机、不同传感器的时钟可能不同步。我习惯以SCADA主站时间为基准,做时间戳的规整。
# 一个简单的SCADA清洗示例(Python伪代码)
import pandas as pd
import numpy as np
def clean_scada(df):
# 1. 删除明显异常值
df = df[(df['wind_speed'] >= 0) & (df['wind_speed'] <= 25)]
df = df[(df['active_power'] >= 0) & (df['active_power'] <= 5000)]
# 2. 缺失值填充(最多前向填充3个点)
df = df.fillna(method='ffill', limit=3)
# 3. 删除连续缺失过多的行
df = df.dropna(thresh=len(df.columns) - 5)
return df
注意:我曾经在一个项目中,直接删除了所有含缺失值的行,结果发现故障发生前的数据恰好被删光了。后来我改用保留+标记的方式,模型效果明显提升。
4.3 振动数据预处理——高频数据的降维艺术
振动数据是高频信号,直接扔进模型是不现实的。我一般分三步走:
- 重采样:把高频振动数据降采样到与SCADA相同的频率(比如10分钟一次)。但降采样前,要先提取统计特征。
- 特征提取:对每个10分钟窗口,计算振动信号的均方根值、峰值、峭度、频谱能量等。这些特征才是模型真正需要的。
- 去噪:用带通滤波器去掉工频干扰和低频噪声。嗯,这里要注意,滤波参数要根据风机型号和转速来调整。
| 特征名称 | 计算公式 | 物理意义 |
|---|---|---|
| 均方根值(RMS) | √(1/N * Σx²) | 振动能量水平 |
| 峰值因子 | 峰值/RMS | 冲击性故障特征 |
| 峭度 | 1/N * Σ((x-μ)/σ)⁴ | 信号分布尖锐程度 |
| 边频带能量 | FFT后特定频带积分 | 齿轮/轴承故障特征 |
说白了,振动数据预处理的核心就是把高频信号压缩成有意义的低维特征。我建议你保留原始数据,但模型训练只用特征。
4.4 气象数据清洗——别被"标准数据"骗了
气象数据看起来最干净,但问题也不少。我遇到过机舱气象站被鸟粪堵住、风向标冻住、风速仪结冰……这些都会导致数据异常。
我的处理方法是:
- 交叉验证:用相邻风机的气象数据做对比,偏差超过20%的标记为可疑。
- 物理约束:风速不能为负,风向在0-360度之间,温度在-40到60度之间。超出范围的直接剔除。
- 时间对齐:气象数据通常每小时一次,需要插值到10分钟粒度。我习惯用三次样条插值,比线性插值更平滑。
小技巧:如果你有测风塔数据,优先用测风塔的数据校正机舱气象站。测风塔更准,但成本高。我在一个海上风场项目里,就是用测风塔数据修正了30%的机舱风速偏差。
4.5 特征工程——让数据"说话"
数据清洗完了,接下来就是特征工程。这一步决定了模型能不能学到有用的模式。我常用的特征工程方法:
- 时序特征:过去1小时、6小时、24小时的平均值、标准差、变化率。故障往往有前兆,这些特征能捕捉趋势。
- 组合特征:风速-功率曲线偏差、温度-转速相关性。这些组合特征比单一特征更有诊断价值。
- 编码特征:风机ID、季节、时段(白天/夜晚)、工况(启机/停机/发电)。这些类别特征要合理编码。
# 特征工程示例
def create_features(df):
# 滚动统计特征
df['wind_avg_1h'] = df['wind_speed'].rolling(6).mean()
df['power_std_6h'] = df['active_power'].rolling(36).std()
# 组合特征:风速-功率偏差
df['power_deviation'] = df['active_power'] - expected_power(df['wind_speed'])
# 时间特征
df['hour'] = df['timestamp'].dt.hour
df['season'] = df['timestamp'].dt.month % 12 // 3 + 1
return df
4.6 数据融合——把三股绳拧成一股
最后一步,是把SCADA、振动、气象数据融合成一张宽表。我建议以SCADA数据的时间戳为主键,左连接振动特征和气象数据。
融合后的数据,每条记录包含:
- 时间戳、风机ID
- SCADA参数(风速、功率、转速、温度等)
- 振动特征(RMS、峰值、峭度等)
- 气象参数(风速、风向、温度、湿度等)
- 标签(是否故障、故障类型、派单优先级)
这张宽表,就是后续模型训练的原材料。我一般会保存两份:一份原始宽表,一份标准化后的训练数据。
数据融合的关键:时间对齐要精确到秒级,否则振动特征和SCADA数据对不上,模型学到的全是噪声。我建议用插值法把振动特征对齐到SCADA的时间戳上。
知识体系总览
下面这张图,是我梳理的数据采集与预处理全流程。你可以把它当作操作手册来用。
这张图把整个流程串起来了。从三个数据源出发,经过各自的清洗和特征提取,最后融合成一张宽表。你照着这个流程做,基本不会出大问题。
我的建议:数据预处理阶段,多花点时间做探索性数据分析(EDA)。画一画风速-功率散点图,看看振动信号的频谱,你会发现很多有意思的规律。这些规律,就是特征工程的灵感来源。
好了,数据采集与预处理就讲到这里。记住一句话:数据质量决定模型上限,特征工程决定模型下限。把这一步做扎实了,后面的模型训练才能事半功倍。