3. 数据预处理:缺失值处理、数据标准化、降维

数据预处理这步,说实话,我见过太多人急着调模型,结果数据一塌糊涂。你想想看,异常检测模型本来就对数据分布敏感,要是原始数据里全是洞、量纲不统一、特征冗余,那训练出来的模型基本是个摆设。

我自己做工业异常检测项目时,有次因为没处理好缺失值,模型在线上连续误报,差点背锅。从那以后我每回跑模型前,都会老老实实把预处理走一遍。

3.1 缺失值处理

异常检测里缺失值是个双刃剑。处理得好,能保留信息;处理不好,会引入偏差。我个人的习惯是,先区分缺失机制——是完全随机缺失(MCAR)、随机缺失(MAR),还是非随机缺失(MNAR)。不过实际项目中,你往往没时间去深究,那就按数据量来定策略。

缺失比例常用方法我的经验评级
< 5%直接删除含缺失的行安全,但心疼数据
5% – 20%均值/中位数/众数填充快速,但会压缩方差
20% – 50%KNN插补 / 多重插补保有分布特征,计算量大
> 50%构建缺失指示器 + 单独建模慎用,容易过拟合

这里有个小坑: 异常检测里用均值填充,会把异常样本拉向正常中心,导致漏检。我记得有一次,一个传感器故障导致的缺失值,被均值填平后,异常模式直接被淹没了。后来我改用KNN插补,才把那个模式找回来。

建议先看看缺失值是否与标签相关。如果缺失本身就暗示异常(比如传感器掉线),那么填充反而是错误。
我在电力异常检测项目里,直接把“是否缺失”作为一个二元特征加进去,模型反而更灵敏。

3.2 数据标准化

异常检测模型大多依赖距离或密度,比如 kNN、LOF、孤立森林。如果特征量纲不统一,一个特征就能主导距离。你不希望“年龄”和“收入”在模型里因为数值范围不同,让你误认为“收入”比“年龄”重要100倍吧?

常用的标准化方法有3种:

  1. Z-score:减去均值,除以标准差。适合数据近似正态分布。
  2. Min-Max:缩放到[0,1]。适合边界明确、无极端值的情况。
  3. RobustScaler:用中位数和四分位距。对异常值鲁棒,我偏爱这个。
# 我自己常用的预处理代码片段
from sklearn.preprocessing import RobustScaler

scaler = RobustScaler()  # 不容易被离群点带偏
X_scaled = scaler.fit_transform(X)
你想想看,在异常检测里,“异常”本身就是少数。用Z-score时,均值和方差会被异常值拉偏,导致正常点被“标准化”成奇怪的值。所以我一般先画个箱线图,看看特征分布,如果离群点很多,果断上RobustScaler。

有一次我在金融交易数据上做异常检测,交易金额特征有少数几笔上千万的,而大部分是几百块。Z-score处理后,正常交易全部挤在-0.2到0.2之间,那几笔异常反而被压成了1.5左右,根本无法区分。换成RobustScaler后,正常和异常的差距就出来了。

3.3 降维

降维在异常检测里有两个作用:一是减少噪声和冗余,让算法聚焦真正的异常模式;二是解决“维数灾难”——高维空间下所有点都稀疏,距离度量失去意义。

我常用的降维路线:

方法适用场景注意点
PCA(主成分分析)线性相关较强,降维后保留方差对异常值敏感,先标准化
t-SNE / UMAP可视化探索,看异常聚类情况计算慢,不能用于在线推理
Autoencoder非线性结构,重构误差做异常分需要大量正常样本
特征选择(方差过滤、互信息)特征极少时,保留最有用的防止丢弃微弱但关键的异常信号

我个人建议,先做一次方差过滤,去掉方差接近0的特征(比如传感器读数一直不变,那这个通道基本没信息)。然后跑PCA,看累计解释方差曲线,保留95%方差所需的主成分数。别一口气降到二维,信息损失太多。

记得——降维之后,要重新验证异常检测效果。我踩过的一个坑:用PCA降到2维后用孤立森林,结果准确率狂掉,因为几个关键的异常模式恰好集中在被丢弃的第三个主成分上。后来我改用Autoencoder的重构误差做异常检测,就稳住了。

3.4 本章知识结构

数据预处理流程(第三章核心) 原始数据 缺失值处理 数据标准化 降维 删除 / 均值填充 / KNN / 指示器 Z-score / MinMax / RobustScaler PCA / t-SNE / Autoencoder / 特征选择 预处理后数据集 💡 核心原则:先看缺失机制,再选标准化方法(优先RobustScaler),最后通过降维保持关键异常信息。 ⚠️ 不要一次性丢弃太多维度,降维后务必用验证集评估异常检测指标。

整张图梳理了数据预处理的三个必经阶段。你看,从原始数据出发,缺失值处理、标准化、降维这三条路最终汇聚到干净的数据集。每一环都可能有坑,但只要你按图上的策略走一遍,基本能稳住。

在实战里,我往往会把缺失值处理和标准化放在同一个 Pipeline 里,用 sklearn 的 Pipeline 串联,这样交叉验证时不会发生数据泄露。你想想看,如果你先把所有数据做了标准化,再切分训练测试集,那测试集信息就提前暴露了——这是很多人忽略的错误。

降维这块,我还想补充一点:不要为了降维而降维。如果原始特征只有十几个,而且业务可解释性很强(比如温度、压力、转速),我宁愿保留全部特征,让模型自己学习重要性。降维的收益在高维(比如 >50 维)时才明显。我曾经在基因组数据上跑异常检测,2000多个特征,PCA降维到50后,孤立森林的 AUC 提升超过15%。