3. 特征工程基础:特征提取、特征选择、标准化与归一化、PCA降维
大家好,我是老张。今天咱们聊聊特征工程。
说实话,在异常检测这个领域摸爬滚打这么多年,我最大的感触就是:模型再牛,也救不了烂特征。你想想看,数据进了模型,模型能看到的只有你给它的特征。特征质量不行,后面再怎么调参、换算法,都是白费力气。
这一节,我带你过一遍特征工程的核心环节。包括特征提取、特征选择、标准化与归一化,还有PCA降维。这些都是我每天都会用到的技术。
核心观点:特征工程不是锦上添花,而是雪中送炭。在异常检测中,好的特征能让模型一眼看出异常,坏的特征则会让模型变成瞎子。
3.1 特征提取:从原始数据中挖金子
特征提取,说白了就是把原始数据变成模型能理解的语言。
我举个例子。你有一台机器的振动信号,原始数据就是一串时间序列。模型直接看这个序列,很难看出门道。但如果你提取出它的均值、方差、峰值、频谱能量,模型就能快速判断机器是否异常。
常用的特征提取方法,我整理了一下:
| 特征类型 | 常用方法 | 适用场景 |
|---|---|---|
| 统计特征 | 均值、方差、偏度、峰度 | 传感器数据、金融数据 |
| 时域特征 | 峰值、均方根、波形因子 | 振动信号、音频信号 |
| 频域特征 | FFT频谱、功率谱密度 | 旋转机械、电力系统 |
| 时频特征 | 小波变换、短时傅里叶变换 | 非平稳信号、瞬态异常 |
我的经验:在工业异常检测中,我习惯先提取20-30个基础特征,然后逐步筛选。别一开始就搞几百个特征,容易过拟合,也浪费时间。
3.2 特征选择:去粗取精
特征提取完了,你手里可能有几十甚至上百个特征。但并不是每个都有用。
我见过不少新手,恨不得把所有特征都塞进模型。结果呢?模型训练慢,效果还差。这就是典型的「垃圾进,垃圾出」。
特征选择的方法,我常用这三种:
- 过滤法:计算每个特征与目标变量的相关性,保留相关性高的。比如用皮尔逊相关系数。
- 包裹法:用模型来评估特征组合的效果。比如递归特征消除(RFE)。
- 嵌入法:在模型训练过程中自动选择特征。比如Lasso回归、树模型的特征重要性。
我曾经在一个风电齿轮箱的异常检测项目中,一开始提取了50个特征。用过滤法筛掉一半,再用包裹法选出15个。模型准确率从82%提升到了94%。
注意:特征选择时,别只看单个特征的重要性。有时候两个单独不重要的特征组合在一起,反而能发挥奇效。这就是特征交互的力量。
3.3 标准化与归一化:让特征站在同一起跑线
这个问题,我几乎每次上课都会被问到:「标准化和归一化到底有什么区别?」
简单说:
- 归一化(Min-Max Scaling):把数据缩放到[0,1]区间。公式是 (x - min) / (max - min)。适合数据分布比较均匀的情况。
- 标准化(Z-score):把数据变成均值为0、标准差为1的分布。公式是 (x - μ) / σ。适合数据有异常值的情况。
我个人的习惯是:如果后续要用PCA或距离类模型(如KNN、SVM),优先做标准化。因为这类模型对特征的尺度非常敏感。
举个例子:
from sklearn.preprocessing import StandardScaler, MinMaxScaler
import numpy as np
# 原始数据
data = np.array([[100, 0.01],
[200, 0.02],
[150, 0.015]])
# 标准化
scaler = StandardScaler()
data_std = scaler.fit_transform(data)
print("标准化后:\n", data_std)
# 归一化
scaler = MinMaxScaler()
data_norm = scaler.fit_transform(data)
print("归一化后:\n", data_norm)
避坑指南:我曾经犯过一个错误——先做了归一化,然后才划分训练集和测试集。结果导致数据泄露,模型在测试集上表现虚高。正确的做法是:先划分数据集,再用训练集的参数去变换测试集。
3.4 PCA降维:化繁为简
PCA,全称主成分分析。它的核心思想很简单:用更少的维度,保留最多的信息。
你想想看,如果我有100个特征,它们之间肯定有相关性。PCA就是把这些相关特征压缩成几个「主成分」,每个主成分都是原始特征的线性组合。
我常用的PCA流程:
- 对数据做标准化(这一步很重要,不然量纲大的特征会主导结果)
- 计算协方差矩阵
- 计算特征值和特征向量
- 按特征值大小排序,选择前k个主成分
代码实现也很简单:
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
# 假设 X 是你的特征矩阵
X_scaled = StandardScaler().fit_transform(X)
# 保留95%的方差
pca = PCA(n_components=0.95)
X_pca = pca.fit_transform(X_scaled)
print(f"原始特征数: {X.shape[1]}")
print(f"降维后特征数: {X_pca.shape[1]}")
print(f"各主成分方差占比: {pca.explained_variance_ratio_}")
关键点:PCA不是万能的。它假设数据是线性相关的,如果数据是非线性的,效果会打折扣。这时候可以考虑t-SNE或UMAP。
我在一个传感器异常检测项目中,原始数据有64维。用PCA降到10维后,不仅模型训练速度提升了5倍,准确率还提高了3%。为什么?因为PCA去掉了噪声维度,让模型更专注于真正的信号。
嗯,特征工程这块内容不少,但核心就这四点:提取、选择、缩放、降维。你把这四个环节练熟了,后面构建异常检测模型就会顺手很多。
公众号:蓝海资料掘金营,微信deep3321