4. 特征工程入门:特征提取、特征选择、特征缩放

各位同学,欢迎来到特征工程这一章。

说实话,在SCADA数据分析里,我见过太多人一上来就扔模型。结果呢?模型跑出来一团糟。为什么?因为原始数据里藏着太多「噪音」和「冗余」。你想想看,SCADA系统每秒采集几百个点,温度、压力、振动、电流……这些数据直接喂给模型,它根本分不清哪个信号是故障前兆,哪个只是正常波动。

特征工程,说白了就是帮模型「划重点」。我个人的习惯是,花在特征工程上的时间,至少占整个项目周期的60%。这一步做扎实了,后面的建模就是水到渠成的事。

核心观点:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限。

4.1 特征提取:从原始信号中「挖」出有用信息

SCADA数据大多是时间序列。比如一个风机齿轮箱的振动信号,原始数据就是一堆电压值。但故障特征不会直接写在电压值里,你得去「提取」。

我在一个风电项目里遇到过这种情况:齿轮箱的振动幅值看起来完全正常,但频谱分析一做,发现某个频率成分悄悄涨了3倍。这就是典型的早期故障信号。如果不做特征提取,这故障根本发现不了。

常用的特征提取方法:

  • 时域特征:均值、方差、峰值、均方根(RMS)、峭度等。这些指标能反映信号的整体能量和波动情况。
  • 频域特征:通过FFT(快速傅里叶变换)把时域信号转到频域。重点关注特定频段的能量分布。比如轴承故障通常会在某个特征频率上出现峰值。
  • 时频域特征:小波变换、短时傅里叶变换。适合处理非平稳信号,比如电机启动瞬间的电流冲击。
  • 统计特征:偏度、峰度、百分位数。这些能描述数据分布的「形状」,对异常检测很有用。

我的经验:对于旋转机械(风机、泵、压缩机),我建议优先提取频域特征。时域特征容易受工况变化干扰,而频域特征往往更稳定。我曾经用峭度指标成功提前48小时预警了一次轴承故障,现场检修时发现滚珠已经出现麻点。

4.2 特征选择:去粗取精,只留「关键先生」

特征提取完了,你可能得到几十甚至上百个特征。但别高兴太早——这里面很多特征是冗余的,甚至是「噪音」。

举个例子:温度和电流在正常工况下高度相关。如果你同时保留这两个特征,模型会「重复学习」,不仅增加计算量,还可能过拟合。

特征选择,就是帮你从一堆特征里挑出最有用那几个。我习惯用「三步走」策略:

  1. 过滤法:先快速筛掉方差接近0的特征(比如某个传感器一直输出恒定值,那它肯定没用)。然后用相关系数矩阵,把相关性高于0.95的特征对去掉一个。
  2. 包裹法:用递归特征消除(RFE),每次去掉一个最不重要的特征,直到模型性能不再提升。这个方法计算量大,但效果最好。
  3. 嵌入法:直接用带正则化的模型(比如Lasso回归)来训练,它会自动把不重要的特征系数压缩到0。

下面是一个用Python做特征选择的简单示例:

import pandas as pd
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.ensemble import RandomForestClassifier

# 假设 X 是特征矩阵,y 是标签(0正常/1故障)
# 方法1:过滤法 - 选择与目标最相关的5个特征
selector = SelectKBest(score_func=f_classif, k=5)
X_selected = selector.fit_transform(X, y)

# 方法2:嵌入法 - 用随机森林的特征重要性
rf = RandomForestClassifier(n_estimators=100)
rf.fit(X, y)
importance = pd.Series(rf.feature_importances_, index=feature_names)
top_features = importance.nlargest(5).index.tolist()
print("最重要的5个特征:", top_features)

避坑指南:我曾经在一个项目里直接用全特征训练模型,结果准确率高达99%。当时我还挺得意,后来发现是因为数据泄露——我把「故障发生后的报警信号」也当成了特征。记住:特征选择必须在训练集上做,不能用到测试集的任何信息。

4.3 特征缩放:让所有特征「站在同一起跑线」

这一步很多人会忽略,但后果很严重。你想想看,振动信号的幅值可能是0.1级别,而电流可能是1000安培级别。如果不做缩放,模型会天然认为「电流更重要」,因为它的数值大。

实际上,数值大小和重要性没有半毛钱关系。特征缩放就是为了消除这种量纲影响。

常用的缩放方法:

方法 公式 适用场景
标准化(Z-score) (x - μ) / σ 数据近似正态分布,适合SVM、线性回归、神经网络
归一化(Min-Max) (x - min) / (max - min) 数据有明确边界,适合KNN、神经网络(输出层用sigmoid时)
鲁棒缩放(RobustScaler) (x - median) / IQR 数据有较多异常值,用中位数和四分位距代替均值和标准差

我个人在SCADA项目中,90%的情况都用标准化。因为SCADA数据里经常有异常尖峰(比如传感器瞬间跳变),如果用Min-Max缩放,这些异常值会把正常数据压缩到很小一个区间,导致信息丢失。而标准化受异常值影响相对小一些。

from sklearn.preprocessing import StandardScaler, MinMaxScaler

# 标准化
scaler_std = StandardScaler()
X_train_std = scaler_std.fit_transform(X_train)
X_test_std = scaler_std.transform(X_test)  # 注意:用训练集的参数转换测试集

# 归一化
scaler_mm = MinMaxScaler(feature_range=(0, 1))
X_train_mm = scaler_mm.fit_transform(X_train)
X_test_mm = scaler_mm.transform(X_test)

重要提醒:一定要先拆分训练集和测试集,再对训练集做fit,然后用训练集的参数去transform测试集。千万别对整个数据集做fit_transform,否则会造成数据泄露,你的模型评估结果会虚高。

4.4 本章知识体系总览

下面这张图总结了特征工程的三个核心步骤,以及它们之间的关系。你可以把它当作一个检查清单,每次做项目时对照着走一遍。

特征工程核心流程 原始SCADA数据 特征提取 时域/频域/时频域/统计 特征选择 过滤/包裹/嵌入 特征缩放 高质量特征集 注意:特征缩放通常在特征选择之后进行, 但也可以根据具体算法灵活调整顺序。 💡 我的建议:先做特征提取,然后用过滤法快速筛选,再用包裹法精挑细选,最后做标准化。这套流程我用了5年,基本没翻过车。

好了,特征工程的核心内容就这些。记住:好的特征工程,能让一个简单的逻辑回归模型跑出比复杂深度学习模型更好的效果。这不是夸张,是我在多个工业项目里验证过的。

专注资料整理