第二章:风电数据基础——SCADA数据解析、振动信号特征、气象数据融合、数据清洗实战

说实话,搞风电运维大模型,最怕什么?

不是模型不够深,不是算力不够强。

是数据本身就不靠谱。

我在风场待了快十年,见过太多「模型跑得飞起,一上线就崩」的案例。追根溯源,十有八九是数据预处理这关没把好。今天咱们就聊聊风电数据的四大金刚:SCADA、振动、气象,以及怎么把它们洗干净喂给模型。

2.1 SCADA数据解析——风机的「体检报告」

SCADA系统,说白了就是风机自己的日志本。每台风机每隔几秒或几分钟,就会记录一堆参数:风速、转速、功率、温度、桨距角……

我习惯把SCADA数据分成三类:

  • 状态量:比如运行、停机、故障码。这些是离散的,别当连续值处理。
  • 模拟量:风速、功率、温度。连续变化,但经常带噪声。
  • 统计量:比如平均值、最大值、最小值。很多SCADA系统会给你算好,但要注意统计窗口是否对齐。

重点提醒:不同风机厂商的SCADA格式千差万别。有的用CSV,有的用二进制,有的甚至直接塞进数据库。我建议第一步先做「字段映射表」,把不同来源的相同物理量统一命名。

举个实际例子。我曾经接手一个项目,A风场和B风场都用同一款风机,但SCADA里「风速」这个字段,一个叫WindSpeed,一个叫WS_Avg,还有一个叫WSPD_10min。不统一的话,模型训练直接乱套。

解析代码其实不复杂,但要注意时间戳的时区问题。很多SCADA记录的是UTC时间,而本地运维日志用的是北京时间。差8个小时,故障定位就全错了。

import pandas as pd

# 我常用的SCADA解析模板
def parse_scada(file_path):
    df = pd.read_csv(file_path, parse_dates=['timestamp'])
    # 统一时区
    df['timestamp'] = df['timestamp'].dt.tz_convert('Asia/Shanghai')
    # 重命名关键字段
    rename_dict = {
        'WindSpeed': 'ws',
        'WS_Avg': 'ws',
        'WSPD_10min': 'ws',
        'ActivePower': 'power',
        'GenRPM': 'rpm'
    }
    df.rename(columns=rename_dict, inplace=True)
    return df

2.2 振动信号特征——听懂风机的「心跳」

SCADA数据是慢变量,几秒甚至十分钟才一条。但振动信号是高频的,每秒几千个采样点。它反映的是风机的机械状态——轴承磨损、齿轮裂纹、叶片不平衡,这些早期故障都会在振动信号里留下痕迹。

我刚开始做振动分析时,犯过一个低级错误:直接把原始振动波形扔进模型。结果模型训练了三天,准确率还不如瞎猜。后来才明白,振动信号需要先提取特征。

常用的特征分两类:

  • 时域特征:均值、方差、峰值、峭度(Kurtosis)。峭度这个指标特别敏感,正常轴承的峭度接近3,一旦出现冲击故障,峭度会飙升到10以上。
  • 频域特征:FFT变换后看各频段的能量分布。齿轮故障通常出现在啮合频率附近,轴承故障则集中在高频段。

我的小技巧:别只盯着原始频谱。试试包络谱分析(Envelope Spectrum),它能放大冲击信号的特征。我在处理齿轮箱故障时,包络谱比原始频谱好使多了。

import numpy as np
from scipy import signal

def extract_vibration_features(vibration_data, fs=2560):
    # 时域特征
    features = {}
    features['rms'] = np.sqrt(np.mean(vibration_data**2))
    features['kurtosis'] = np.mean((vibration_data - np.mean(vibration_data))**4) / (np.std(vibration_data)**4)
    features['peak'] = np.max(np.abs(vibration_data))
    
    # 频域特征:计算1/3倍频程能量
    freqs, psd = signal.welch(vibration_data, fs, nperseg=1024)
    # 提取0-100Hz, 100-500Hz, 500-2000Hz三个频段能量
    bands = [(0, 100), (100, 500), (500, 2000)]
    for i, (low, high) in enumerate(bands):
        mask = (freqs >= low) & (freqs < high)
        features[f'band_{i}_energy'] = np.sum(psd[mask])
    
    return features

2.3 气象数据融合——别让模型「看天吃饭」

风机是跟老天爷打交道的设备。风速、风向、温度、气压、湿度、湍流强度……这些气象因素直接影响发电效率和设备寿命。

但气象数据有个大坑:空间分辨率不够。气象站的网格通常是几公里甚至几十公里一个点,而风机之间可能只隔几百米。地形起伏、尾流效应,都会让实际风速跟气象预报差很多。

我建议的做法是:

  • 优先使用机舱风速计:虽然它受叶轮旋转影响有误差,但至少是真实测量值。
  • 气象数据做插值:用反距离加权(IDW)或克里金法,把气象站数据插值到每台风机的位置。
  • 加入湍流强度:这个参数很多团队会忽略。湍流强度高,意味着风速剧烈波动,对风机疲劳载荷影响很大。

注意:气象数据和SCADA数据的时间分辨率往往不一致。气象数据通常是小时级,SCADA是分钟级。融合前一定要做重采样,我一般把SCADA数据聚合到小时级,跟气象数据对齐。

def fuse_weather_scada(scada_df, weather_df):
    # 重采样SCADA到小时级
    scada_hourly = scada_df.resample('1H', on='timestamp').mean()
    # 合并气象数据
    merged = pd.merge(scada_hourly, weather_df, on='timestamp', how='left')
    # 前向填充缺失的气象数据(气象站偶尔断传)
    merged.fillna(method='ffill', inplace=True)
    return merged

2.4 数据清洗实战——脏数据是模型的「毒药」

数据清洗这事,听起来简单,做起来全是坑。我见过最离谱的一次,某台风机SCADA记录的风速常年稳定在12m/s,但功率输出却是0。查了半天,原来是风速计被鸟屎糊住了。

清洗流程我总结为四步:

  1. 缺失值处理:连续缺失超过1小时的,直接标记为停机时段。短时间缺失,用前后均值插补。
  2. 异常值检测:用3-sigma法则或IQR(四分位距)方法。但要注意,风机在极端工况下(比如切出风速附近)的数据看起来像异常,其实是正常的。
  3. 逻辑校验:风速为0但功率不为0?风速很大但转速很低?这些物理上不可能的组合,直接剔除。
  4. 停机时段剔除:风机维护、电网限电、故障停机期间的数据,不能用于训练。我习惯用功率曲线做筛选——如果风速-功率点明显偏离标准功率曲线,大概率是停机状态。

避坑指南:我曾经用一套包含大量停机数据的数据集训练模型,结果模型学会了「不管风速多少,输出功率都是0」。后来加了一个「运行状态」标签,才把问题解决。记住:模型只学它看到的东西,你喂给它垃圾,它就学垃圾。

def clean_wind_data(df):
    # 1. 缺失值处理
    df = df.interpolate(method='linear', limit=6)  # 最多插补6个连续缺失
    
    # 2. 异常值检测(以风速为例)
    q1 = df['ws'].quantile(0.25)
    q3 = df['ws'].quantile(0.75)
    iqr = q3 - q1
    df = df[(df['ws'] >= q1 - 1.5*iqr) & (df['ws'] <= q3 + 1.5*iqr)]
    
    # 3. 逻辑校验:风速>0且功率=0,标记为停机
    df.loc[(df['ws'] > 0.5) & (df['power'] < 0.1), 'status'] = 'shutdown'
    
    # 4. 剔除停机时段
    df_clean = df[df['status'] != 'shutdown'].copy()
    return df_clean

知识体系总览

下面这张图,是我自己梳理的风电数据基础框架。每次带新人,我都会先让他们看这张图——搞清楚数据从哪里来、长什么样、怎么处理,比直接调模型重要得多。

风电数据基础知识体系 SCADA数据 振动信号 气象数据 其他数据 数据解析与格式统一 特征提取(时域/频域/统计特征) 多源数据融合(时间对齐/空间插值) 数据清洗(缺失/异常/逻辑校验/停机剔除)

嗯,数据基础这块就聊到这儿。记住一句话:模型的上限,由数据质量决定。花80%的时间在数据上,20%的时间调模型,这才是风电运维的正确姿势。


专注资料整理