异常检测实战:统计方法、隔离森林、AutoEncoder 与不平衡学习

异常检测与不平衡学习实战:异常检测问题定义、统计方法(Z-score/IQR/MAD)、无监督方法(隔离森林/OneClassSVM/LocalOutlierFactor)、深度学习(AutoEncoder 重构误差)、类别不平衡处理(重采样/代价敏感/阈值)、评估与落地。

引言

欺诈交易、服务器故障、设备损坏——这些「异常」在数据里只占极小比例,却是最有价值的部分。异常检测(Anomaly Detection)的目标不是「分好多数类」,而是找出少数异常。它与类别不平衡问题紧密相关:异常极稀少、正负比例悬殊。本文覆盖从统计方法到隔离森林、AutoEncoder 的完整武器库,以及不平衡学习的处理套路与评估指标。

前置:/ml-model-evaluation/(评估与混淆矩阵)、/ml-supervised-classification/(分类与不平衡)、/ml-deep-learning-advanced/(神经网络基础)。


目录


1. 异常检测问题定义与场景

1.1 什么是异常

异常 = 与绝大多数数据「行为显著不同」的点。三类典型:

类型例子
点异常一笔金额 100 万的转账
上下文异常深夜的高频登录
集体异常一批账号同时小额转账

1.2 与分类的区别

  • 分类:有标签、样本均衡
  • 异常检测:标签稀少/缺失、极度不均衡、异常「不是一类而是很多种」

记忆:异常检测找少数「另类」点,异常种类多且标签少;欺诈/故障/设备监控是高频场景。


2. 统计方法:Z-score、IQR 与 MAD

2.1 Z-score

偏离均值几个标准差:

import numpy as np
z = np.abs((x - x.mean()) / x.std())
outliers = z > 3   # 超过 3 个标准差

缺点:受异常本身污染均值和标准差(masking)。

2.2 IQR 与 MAD(更稳健)

# IQR:四分位距
q1, q3 = np.percentile(x, [25, 75]); iqr = q3 - q1
outliers = (x < q1 - 1.5*iqr) | (x > q3 + 1.5*iqr)

# MAD:中位数绝对偏差,比标准差更抗异常
mad = np.median(np.abs(x - np.median(x)))
threshold = 3 * 1.4826 * mad
outliers = np.abs(x - np.median(x)) > threshold

记忆:Z-score 快但易被异常污染;IQR/MAD 用分位数和中位数更稳健,异常检测首选稳健统计量。


3. 无监督方法总览

方法思路适用
隔离森林好切=易隔离高维表格数据
OneClassSVM找边界超平面中等维度、流形
LocalOutlierFactor邻域密度比较局部密度差异
AutoEncoder重构误差高维/图像/序列

无监督 = 不需要标签,靠「结构差异」定义异常。

记忆:无监督异常检测四类——隔离森林/OneClassSVM/LOF/AutoEncoder,各有擅长的数据结构。


4. 隔离森林:用「好切」找异常

4.1 直觉

随机切数据:异常点分布稀疏,几下就被切出来;正常点密集,需要很多刀。

正常点:随机树中路径很深(难隔离)
异常点:随机树中路径很浅(易隔离)
异常分数 = 平均路径深度(越浅越异常)

4.2 代码

from sklearn.ensemble import IsolationForest

iso = IsolationForest(
    n_estimators=200, contamination=0.01,   # 预期异常比例
    random_state=42)
iso.fit(X)                       # 无标签!
scores = iso.decision_function(X)  # 越低越异常
pred = iso.predict(X)              # -1 异常 / 1 正常

4.3 特点

  • 快、可并行、高维尚可
  • contamination 需按业务预估异常率
  • 对正常模式固定的数据效果好

记忆:隔离森林用随机切分的路径深度找异常——异常易隔离路径浅;contamination 设预期异常率,predict 返回 -1/1。


5. One-Class SVM 与 Local Outlier Factor

5.1 One-Class SVM

在高维空间找「包含大部分数据的边界」,边界外即异常:

from sklearn.svm import OneClassSVM

ocsvm = OneClassSVM(kernel='rbf', gamma=0.1, nu=0.01)   # nu≈异常比例
ocsvm.fit(X)
pred = ocsvm.predict(X)   # -1 异常

5.2 Local Outlier Factor(LOF)

比较样本与其近邻的局部密度:密度远低于邻域 = 异常:

from sklearn.neighbors import LocalOutlierFactor

lof = LocalOutlierFactor(n_neighbors=20, contamination=0.01)
pred = lof.fit_predict(X)      # -1 异常(自监督,无 fit 分数)

记忆:OneClassSVM 用边界超平面圈正常区;LOF 比较局部密度;二者对数据尺度敏感,先标准化。


6. AutoEncoder:重构误差即异常分

6.1 思路

用正常数据训练一个自编码器:正常样本重构好(误差小),异常样本重构差(误差大)——重构误差就是异常分数。

6.2 PyTorch 实现骨架

import torch, torch.nn as nn

class AE(nn.Module):
    def __init__(self, in_dim, h_dim=32):
        super().__init__()
        self.enc = nn.Sequential(nn.Linear(in_dim, h_dim*2), nn.ReLU(),
                                 nn.Linear(h_dim*2, h_dim))
        self.dec = nn.Sequential(nn.Linear(h_dim, h_dim*2), nn.ReLU(),
                                 nn.Linear(h_dim*2, in_dim))
    def forward(self, x):
        return self.dec(self.enc(x))

# 只在正常数据上训练,最小化 MSE
model = AE(X_normal.shape[1])
# ... 训练循环 ...
with torch.no_grad():
    rec_err = torch.mean((model(X_all) - X_all)**2, dim=1)  # 异常分

6.3 变体

  • 卷积自编码器:图像异常检测
  • LSTM 自编码器:时间序列异常
  • VAE:用重建似然替代 MSE

记忆:AutoEncoder 只在正常数据上训练,重构误差大的样本判异常;配卷积/LSTM 可做图像/时序异常。


7. 类别不平衡:重采样与代价敏感

7.1 数据层面:重采样

from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import RandomUnderSampler

sm = SMOTE(random_state=42)            # 少数类合成过采样
X_res, y_res = sm.fit_resample(X, y)
# 或 combined = SMOTEENN(...) 过采样+清洗

7.2 算法层面:代价敏感

# 给少数类更高权重
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(class_weight='balanced_subsample', random_state=42)

7.3 阈值层面

不用默认 0.5 概率阈值,按业务要求调
阈值 → 用验证集上 Precision/Recall 权衡选

记忆:不平衡三条路——SMOTE 重采样(数据)、class_weight 加权(算法)、按业务调概率阈值(决策)。


8. 阈值选择:权衡召回与误报

8.1 Precision-Recall 曲线选点

from sklearn.metrics import precision_recall_curve

precision, recall, thresholds = precision_recall_curve(y_val, scores)
# 选业务可接受的召回/精度组合
# 如欺诈:宁可误报也要召回高 → 选低阈值

8.2 业务目标驱动

场景侧重点
欺诈风控高召回(宁误报不漏)
设备故障高精度(避免停产误操作)
质量检测平衡 + 人工复核

记忆:阈值别用 0.5 默认——用 PR 曲线按业务选点;欺诈要高召回、设备要高精度。


9. 评估与落地:精度陷阱

9.1 精度陷阱

异常只有 1%,瞎猜「全部正常」精度 99%——精度完全无意义。异常检测看:

  • Precision / Recall / F1(对异常类)
  • PR-AUC(类别极不均衡时的首选)
  • 业务成本(漏一个损失 vs 误报一个成本)

9.2 落地要点

# 评估只看异常类的指标
from sklearn.metrics import classification_report
print(classification_report(y_test, pred, labels=[1], target_names=['anomaly']))
  • 用真实分布评估(别在过采样后的数据上测)
  • 监控:线上定期重训练,漂移会摧毁异常检测
  • 与人工复核闭环:标注可疑样本回炉

记忆:异常检测别信精度——异常占比低时全猜正常也 99% 精度;看异常类的 PR/F1 与 PR-AUC,用业务成本定阈值,线上要监控漂移并人工复核闭环。


10. 速查表与一句话记忆

方法类型关键点
Z-score统计受污染,快
IQR/MAD统计稳健
隔离森林无监督路径深度、contamination
OneClassSVM无监督nu≈异常比例
LOF无监督局部密度
AutoEncoder深度重构误差
SMOTE数据少数类合成
class_weight算法代价敏感
PR 曲线评估按业务选阈值

一句话记忆:异常检测找少数「另类」点——统计方法用 IQR/MAD(比 Z-score 稳健),无监督方法用隔离森林(路径深度)、OneClassSVM(边界)、LOF(密度)、AutoEncoder(重构误差);类别不平衡用 SMOTE 重采样 + class_weight 加权 + 按业务调阈值;评估别信精度(全猜正常也 99%),看异常类的 Precision/Recall/F1 与 PR-AUC,线上监控漂移、人工复核闭环。


延伸阅读

  • /ml-model-evaluation/ — 评估指标与交叉验证
  • /ml-supervised-classification/ — 分类与类别不平衡
  • /ml-deep-learning-advanced/ — 神经网络与自编码器基础
  • /ml-feature-engineering/ — 异常检测特征构建
  • /ml-model-deployment/ — 检测模型上线与监控
  • [[ai-ml]] — 算法原理深度专题
  • scikit-learn 异常检测文档

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「ml」更多文章

  1. 集成学习实战:Bagging、随机森林、梯度提升与 Stacking
  2. 迁移学习实战:预训练模型、特征提取与微调全流程
  3. 计算机视觉入门实战:图像处理与 CNN 图像分类