3. 数据预处理基础:缺失值处理、异常值检测、数据标准化与归一化

各位同行,大家好。我是老张,在风场摸爬滚打了十来年,后来又搞了几年AI算法。今天咱们聊聊数据预处理。

很多人觉得,模型搭得好,结果就漂亮。其实不然。我见过太多项目,算法选得再牛,数据一塌糊涂,最后全白搭。说白了,数据预处理就是给模型「喂饭」。饭馊了,再好的厨师也做不出好菜。

咱们风机数据,尤其如此。SCADA系统采集的数据,那叫一个「脏」。传感器漂移、通讯中断、极端工况……各种问题。今天我就把压箱底的经验掏出来,跟大伙儿聊聊这三板斧:缺失值、异常值、标准化。

数据预处理核心流程 缺失值处理 异常值检测 标准化与归一化 删除法 · 填充法 · 插值法 3σ原则 · IQR · 孤立森林 Min-Max · Z-score · Robust ⚠️ 顺序很重要:先处理缺失值 → 再检测异常值 → 最后做标准化 因为异常值检测依赖完整数据,标准化依赖数据分布稳定

3.1 缺失值处理:别让「空」坑了模型

风机数据里,缺失值太常见了。通讯闪断、传感器故障、维护停机……都会导致数据点丢失。我刚开始做预测时,直接删掉了所有含缺失值的行。结果呢?模型训练出来,一到雷雨天气就失灵。后来才发现,我把故障前的关键数据全删了。

⚠️ 注意: 不要盲目删除缺失值!尤其是时序数据,删除会破坏时间连续性。

3.1.1 常见的缺失值处理方法

方法 适用场景 优点 缺点
直接删除 缺失比例 < 5%,且随机分布 简单粗暴 丢失信息,破坏时序
均值/中位数填充 数值型特征,缺失比例不高 计算快,不影响分布 降低方差,可能引入偏差
前向/后向填充 时序数据,短时间缺失 保持趋势 长缺失段效果差
插值法 时序数据,缺失段平滑 拟合自然 计算量大
模型预测填充 重要特征,缺失比例高 精度高 耗时,可能过拟合

我个人习惯,对于风机SCADA数据,优先用前向填充。为什么?因为传感器数据变化是连续的,前一秒的值最接近下一秒。比如风速,不会突然从5m/s跳到15m/s。当然,如果缺失超过10个连续点,我会改用线性插值。

💡 我的经验: 对于振动数据,千万别用均值填充!振动信号波动大,均值会抹掉故障特征。我一般用前向填充 + 标记缺失位置。
import pandas as pd
import numpy as np

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

# 查看缺失情况
print(df.isnull().sum())

# 前向填充(ffill)—— 我最常用的方法
df['wind_speed'] = df['wind_speed'].ffill()

# 如果缺失较多,用线性插值
df['power_output'] = df['power_output'].interpolate(method='linear')

# 标记缺失位置(可选)
df['is_missing'] = df['wind_speed'].isnull().astype(int)

3.2 异常值检测:揪出「捣乱」的数据点

异常值,说白了就是「不听话」的数据。风机运行中,传感器偶尔会抽风,比如风速突然显示99m/s,或者功率变成负数。这些数据如果不处理,模型会学歪。

我曾经遇到过一个案例:某台风机振动值突然飙升,但SCADA系统没报警。我查了原始数据,发现是传感器接线松动,导致信号跳变。如果当时用异常值检测,就能提前发现,避免误判。

3.2.1 三种常用检测方法

方法一:3σ原则(拉依达准则)

假设数据服从正态分布,超出均值±3倍标准差的值视为异常。简单有效,但要求数据分布不能太偏。

def detect_outliers_3sigma(data, threshold=3):
    mean = np.mean(data)
    std = np.std(data)
    outliers = np.abs(data - mean) > threshold * std
    return outliers

# 对风速做检测
df['wind_outlier'] = detect_outliers_3sigma(df['wind_speed'])
print(f"检测到 {df['wind_outlier'].sum()} 个异常风速点")

方法二:IQR(四分位距法)

不依赖正态分布,用Q1和Q3的差值判断。鲁棒性更强,适合偏态分布。我个人更推荐这个方法,因为风机数据往往不是正态的。

def detect_outliers_iqr(data):
    Q1 = data.quantile(0.25)
    Q3 = data.quantile(0.75)
    IQR = Q3 - Q1
    lower = Q1 - 1.5 * IQR
    upper = Q3 + 1.5 * IQR
    return (data < lower) | (data > upper)

df['power_outlier'] = detect_outliers_iqr(df['power_output'])

方法三:孤立森林(Isolation Forest)

这是机器学习方法,适合高维数据。它不假设分布,通过随机切割来「孤立」异常点。我一般在做多特征联合检测时用,比如同时看风速、功率、桨距角。

from sklearn.ensemble import IsolationForest

# 多特征联合检测
features = ['wind_speed', 'power_output', 'pitch_angle']
iso_forest = IsolationForest(contamination=0.05, random_state=42)
df['iso_outlier'] = iso_forest.fit_predict(df[features])
# -1 表示异常,1 表示正常
df['iso_outlier'] = df['iso_outlier'].map({1: 0, -1: 1})
🔑 关键点: 异常值不一定要删除!如果是传感器故障导致的,果断删。如果是真实极端工况(比如切出风速),建议保留或单独标记。我一般会建一个「异常标记列」,而不是直接删除。

3.3 数据标准化与归一化:让特征「平起平坐」

你想想看,风速范围0-30m/s,功率范围0-2000kW,温度范围-20-50℃。这些特征量纲不同,直接丢进模型,数值大的特征会主导学习过程。尤其是神经网络和距离类算法(如KNN、SVM),对尺度特别敏感。

3.3.1 归一化(Min-Max Scaling)

把数据压缩到[0,1]区间。公式很简单:(x - min) / (max - min)。适合数据有明确边界的情况,比如风速、温度。

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
df[['wind_speed', 'power_output']] = scaler.fit_transform(
    df[['wind_speed', 'power_output']]
)

3.3.2 标准化(Z-score)

把数据变成均值为0、标准差为1的分布。公式:(x - mean) / std。适合数据可能有异常值的情况,因为它不依赖最大值最小值。

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
df[['vibration_x', 'vibration_y']] = scaler.fit_transform(
    df[['vibration_x', 'vibration_y']]
)

3.3.3 鲁棒标准化(Robust Scaling)

用中位数和IQR代替均值和标准差。对异常值不敏感。我处理振动数据时特别喜欢用这个,因为振动信号经常有尖峰。

from sklearn.preprocessing import RobustScaler

scaler = RobustScaler()
df[['vibration_z']] = scaler.fit_transform(df[['vibration_z']])
💡 我的建议: 对于风机故障预测,我一般先做标准化(Z-score),因为后续模型(如LSTM、XGBoost)对标准化更友好。如果数据有明显边界,比如角度0-360°,我会用归一化。

3.4 预处理流程总结

好了,咱们捋一捋。数据预处理不是随便搞搞,得有章法。我总结了一个四步流程:

  1. 先看数据概貌:用df.describe()df.info()了解缺失、分布、范围。
  2. 处理缺失值:时序数据用前向填充,非时序用中位数填充。
  3. 检测异常值:单特征用IQR,多特征用孤立森林。标记但不一定删除。
  4. 标准化/归一化:根据模型选择。树模型可以不标准化,但神经网络必须做。

嗯,这里要注意:预处理顺序不能乱。先标准化再做异常检测?那异常值会被「抹平」,就检测不出来了。所以一定是:缺失值 → 异常值 → 标准化。

最后说一句,数据预处理没有「万能药」。每个风场、每台机组都有自己的脾气。多看看数据分布,多试试不同方法,慢慢就有感觉了。

📌 核心要点:
  • 缺失值:前向填充是时序数据的首选
  • 异常值:IQR法鲁棒性好,孤立森林适合多特征
  • 标准化:Z-score通用,Min-Max适合有边界数据
  • 顺序:缺失值 → 异常值 → 标准化,不可颠倒

公众号:蓝海资料掘金营,微信deep3321