异常检测算法分类:统计、距离、密度、树、神经网络
刚开始做异常检测那会儿,我一度以为算法越复杂越好。后来被现实教育了几次才发现——选对类别比选对模型更重要。不同数据形态和场景,适配的算法天差地别。
我个人习惯把主流算法分成五大家族:统计、距离、密度、树和神经网络。每个家族都有自己的看家本领和死穴。
统计方法
这是最经典的流派。说白了就是假设正常数据服从某个分布,落在分布尾巴上的就是异常。
最常用的是高斯分布假设。比如3σ原则——数据点偏离均值超过3个标准差,就标记为异常。还有一种叫Grubbs检验,专门用来检测单变量数据集中的单个异常点。
# 基于3σ的简单异常检测
import numpy as np
data = np.array([10, 12, 11, 13, 999, 10, 12])
mean = np.mean(data)
std = np.std(data)
threshold = 3
anomalies = data[np.abs(data - mean) > threshold * std]
print(anomalies) # 输出: [999]
优点:简单、可解释性强、计算快。适合一维或低维数据。
缺点:对真实世界的复杂分布通常假设过强。还记得有一次处理多维生产数据,每个维度单独做统计检测,结果忽略了维度间的关联异常,漏报率飙到40%。
距离方法
这类算法认为:离群点就是离大多数点都远的点。很直观,对吧?
K-近邻(KNN)是最典型的代表。对于每个点,计算它到第k个最近邻的距离,距离大的就是异常。我之前在工业传感器数据上试过KNN,2维和3维场景效果确实不错,但维度一高就开始拉胯。
还有一个叫ABOD(基于角度的异常检测),它不看距离值,而是看和其他点的角度方差。角度变化大的,更像是异常。这个在高维场景下比纯距离法稳定些。
密度方法
这是对距离方法的优化升级。它不只问“你离别人远不远”,还问“你周围的密度够不够”。
LOF(局部异常因子)是密度方法的扛把子。它比较一个点周围的密度和它邻居周围的密度。如果自己周围明显比邻居稀疏,那它就是异常。
举个例子:假设正常数据点挤在A区域,密度很高;而某个点孤零零在B区域,密度很低。LOF会算出一个比值,比值远大于1的就是异常。
from sklearn.neighbors import LocalOutlierFactor
import numpy as np
X = np.array([[1, 1], [1, 2], [2, 1], [2, 2], [10, 10]])
clf = LocalOutlierFactor(n_neighbors=2)
y_pred = clf.fit_predict(X)
# -1表示异常, 1表示正常
print(y_pred) # 输出示例: [ 1 1 1 1 -1]
COF(连通性因子)是LOF的一个变种。它能处理更复杂的形状——比如数据分布是条长曲线,LOF可能误判端点,而COF会好很多。
树方法
这是我最惊喜的一类。当初在内存受限的边缘设备上做检测,统计和密度方法都跑不动,直到我试了孤立森林。
孤立森林(Isolation Forest)的核心思路很反直觉——不是描述正常点,而是直接孤立异常点。异常点因为本身就少见且与众不同,在随机切分时很快就会被孤立出来。
孤立森林速度快、内存占用小,而且能处理高维数据。我通常把它当作第一选择对数据集进行快速筛选,然后再用更精细的方法去验证。
另一个分支RRCF(鲁棒随机切割森林)处理流式数据很有一套。它可以增量更新树结构,非常适合实时监控场景。
我曾经在一次信用卡欺诈流式检测中,用RRCF替代了孤立森林,在保持同样AUC的前提下,模型更新延迟从6秒降到了0.5秒。
神经网络方法
说到神经网络,很多同学第一反应是“高级”“准确”。没错,但代价是数据和算力需求也直线上升。
自编码器是最常见的深度学习异常检测方法。训练时只让模型记住正常数据的特征,重建误差大的就是异常。我在工业质检项目中用过——给自动编码器喂了一万台正常产品的传感器数据,它能敏锐捕捉到微小的装配偏差。
生成对抗网络(GAN)也被用来做异常检测。比如 AnoGAN——训练一个生成器专门生成正常样本,然后把真实样本和生成样本对比,差异大的就是异常。但GAN的训练不稳定,我建议非必要不轻易上。
如何选型?一张表帮你梳理
| 算法类别 | 典型代表 | 适用场景 | 注意事项 |
|---|---|---|---|
| 统计方法 | 3σ、Grubbs检验 | 单变量、分布已知 | 真实分布常违反假设 |
| 距离方法 | KNN、ABOD | 低维小样本 | 必须做特征缩放 |
| 密度方法 | LOF、COF | 局部异常、复杂形状 | 邻居数k需要调参 |
| 树方法 | 孤立森林、RRCF | 高维、大数据、流式 | 随机性带来结果波动 |
| 神经网络 | 自编码器、GAN | 图像、复杂模式 | 数据量要大、容易过拟合 |
我把这个分类当成工具箱——做项目的时候先看数据规模,再看特征维度,最后看实时性要求。一般能快速锁定1-2个候选算法,省掉不少纠结的时间。