第3章:数据采集与预处理——SCADA数据采集原理、数据清洗、标准化与归一化

各位好,我是老张。在风电行业摸爬滚打了十几年,今天咱们聊聊数据预处理。

说实话,很多刚入行的朋友,一上来就急着建模型。结果呢?模型跑出来一塌糊涂。为什么?因为数据没处理好。我见过太多这样的案例了。数据预处理,说白了就是给模型喂“干净饭”。你喂它馊掉的饭菜,它怎么可能给你好好干活?

核心观点:数据预处理占整个建模工作量的60%以上。别嫌烦,这一步省了,后面全是坑。

3.1 SCADA数据采集原理

SCADA系统,全称是监控与数据采集系统。咱们风场里,每台风机上都装着几十个传感器。风速、转速、温度、振动、功率……这些数据,每秒钟都在产生。

采集频率一般是10分钟一次。为什么是10分钟?我个人习惯是,这个频率既能捕捉到设备的动态变化,又不会产生太多冗余数据。你想想看,如果每秒采集一次,一台风机一天就是86400条数据。一个风场几十台风机,数据量太大了,存储和处理都是问题。

SCADA采集的数据类型,我整理了一下:

数据类型 典型参数 采集频率
环境参数 风速、风向、环境温度、气压 10分钟
运行参数 发电机转速、桨距角、偏航角度 10分钟
温度参数 齿轮箱油温、发电机绕组温度、轴承温度 10分钟
振动参数 主轴振动、齿轮箱振动 1秒或更高
电气参数 有功功率、无功功率、电压、电流 10分钟

嗯,这里要注意。振动参数是高频采集的,因为它能反映齿轮的早期故障。我在项目中遇到过,有一次齿轮箱的振动数据突然出现了一个微小的尖峰,当时没在意。结果三个月后,齿轮箱直接报废了。从那以后,我对振动数据格外敏感。

3.2 数据清洗——缺失值处理

数据采集回来了,但问题来了。传感器会坏,通信会断,数据会丢。这就是缺失值。

缺失值怎么处理?我一般分三种情况:

  • 少量缺失(<5%):直接删除。省事,不影响大局。
  • 中等缺失(5%-20%):用插值法。线性插值、均值插值都行。
  • 大量缺失(>20%):这个特征就别用了。强行补全只会引入噪声。

举个例子,风速数据缺失了。你可以用前后两个时刻的风速取平均。但如果是温度数据,我建议用同一天同一时刻的历史均值。为什么?因为温度有日周期规律。你想想看,中午的温度和凌晨的温度能一样吗?

我的小技巧:对于连续缺失超过3个时间点的数据,我建议直接标记为“不可用”。因为插值法在长段缺失时,误差会累积,反而误导模型。

# 缺失值处理示例(Python伪代码)
import pandas as pd
import numpy as np

# 读取SCADA数据
df = pd.read_csv('wind_turbine_data.csv')

# 检查缺失率
missing_rate = df.isnull().sum() / len(df)

# 处理策略
for col in df.columns:
    if missing_rate[col] < 0.05:
        # 少量缺失,直接删除
        df.dropna(subset=[col], inplace=True)
    elif missing_rate[col] < 0.2:
        # 中等缺失,线性插值
        df[col].interpolate(method='linear', inplace=True)
    else:
        # 大量缺失,删除该特征
        df.drop(columns=[col], inplace=True)

3.3 数据清洗——异常值处理

异常值,说白了就是“离谱的数据”。比如风速显示100m/s,这明显不对。台风来了也没这么夸张。

异常值怎么找?我常用两种方法:

  1. 3σ原则:数据在均值±3倍标准差之外,视为异常。
  2. 箱线图法:数据在上下四分位数之外1.5倍IQR,视为异常。

我曾经犯过一个错误。有一次,齿轮箱油温数据出现了几个异常高的点。我直接用3σ原则把它们删了。结果后来发现,那其实是齿轮箱开始过热的前兆。删掉之后,模型完全没学到这个规律。

避坑指南:异常值不一定是“坏数据”。它可能是故障的前兆。处理前,一定要先判断:这是传感器噪声,还是真实的物理异常?我建议先标记,不要直接删除。

# 异常值检测示例
from scipy import stats

# 3σ原则
z_scores = np.abs(stats.zscore(df['wind_speed']))
df['wind_speed_clean'] = np.where(z_scores > 3, np.nan, df['wind_speed'])

# 箱线图法
Q1 = df['gear_oil_temp'].quantile(0.25)
Q3 = df['gear_oil_temp'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
df['gear_oil_temp_clean'] = df['gear_oil_temp'].clip(lower_bound, upper_bound)

3.4 数据标准化与归一化

数据清洗完了,但还有一个问题。不同特征的量纲不一样。风速是0-30m/s,温度是-20到80℃,功率是0-2000kW。这些数据直接扔进模型,量纲大的特征会主导模型训练。

解决办法就是标准化或归一化。

  • 归一化(Min-Max Scaling):把数据缩放到[0,1]区间。公式:X' = (X - X_min) / (X_max - X_min)
  • 标准化(Z-score Scaling):把数据变成均值为0,标准差为1。公式:X' = (X - μ) / σ

我个人习惯是:如果数据分布比较均匀,用归一化。如果数据有异常值,用标准化。为什么?因为归一化对异常值敏感,一个极端值会把其他数据都压缩到很小的区间。

重要提醒:标准化和归一化的参数(均值、标准差、最大值、最小值),一定要用训练集计算,然后应用到测试集。千万不能用全量数据计算。否则会造成数据泄露,模型评估结果会虚高。

# 标准化与归一化示例
from sklearn.preprocessing import MinMaxScaler, StandardScaler

# 归一化
scaler_minmax = MinMaxScaler()
df_scaled = scaler_minmax.fit_transform(df[['wind_speed', 'power']])

# 标准化
scaler_std = StandardScaler()
df_standardized = scaler_std.fit_transform(df[['wind_speed', 'power']])

3.5 本章知识体系

下面这张图,是我自己画的。它把本章的知识结构串起来了。你一看就明白:数据预处理不是孤立的一步,而是一个环环相扣的流程。

数据预处理知识体系 SCADA数据采集 数据清洗:缺失值处理 少量缺失:删除 中等缺失:插值 大量缺失:删除特征 数据清洗:异常值处理 3σ原则 箱线图法 标准化与归一化 归一化:[0,1]区间 标准化:均值0,方差1 关键提醒 异常值不一定是 坏数据 先标记,再处理

嗯,这张图你看懂了吗?从上到下,SCADA采集→缺失值处理→异常值处理→标准化/归一化。每一步都有对应的策略。我建议你把这个流程记下来,以后做项目直接套用。

好了,数据预处理就讲到这里。记住一句话:数据质量决定模型上限。你花80%的时间在数据上,模型自然给你好结果。


蓝海数据掘金营,专注资料整理