【深度学习|学习笔记】异常检测概论 — 从经典算法到深度学习(含实用 Python 示例)
【深度学习|学习笔记】异常检测概论 — 从经典算法到深度学习(含实用 Python 示例)
【深度学习|学习笔记】异常检测概论 — 从经典算法到深度学习(含实用 Python 示例)
文章目录
- 【深度学习|学习笔记】异常检测概论 — 从经典算法到深度学习(含实用 Python 示例)
- 异常检测概论 — 从经典算法到深度学习(含实用 Python 示例)
- 1. 什么是异常检测(Why & What)
- 定义:
- 任务形式:
- 应用场景:
- 2. 评估指标(怎么衡量好坏)
- 3. 数据类型与问题细分
- 4. 经典(非深度)方法(直观 + 优/缺点)
- 4.1 统计方法
- 4.2 距离 / 密度基方法
- 4.3 树 / 集成方法
- 4.4 线性降维与子空间方法
- 5. 深度学习方法(近年主流 — 对复杂数据尤其有效)
- 5.1 自编码器 (AE)
- 5.2 变分自编码器 (VAE)
- 5.3 GAN-based 方法(如 AnoGAN / f-AnoGAN)
- 5.4 对比学习与自监督
- 5.5 专用架构
- 5.6 Parameter-efficient / hybrid
- 6. 时序异常检测(专门技巧)
- 7. 实践工作流(工程化)
- 8. 常见挑战与注意点
- 9. 实战策略(best-practices)
- 10. Python 示例(A:经典方法;B:深度自编码器)
- 示例 A — 经典方法(合成数据 + IsolationForest / LOF / OneClassSVM)
- 示例 B — 深度自编码器(PyTorch,基于 MNIST: 将部分数字设为异常)
- 11. 进一步阅读 / 常用工具(简短)
- 12. 小结
欢迎铁子们点赞、关注、收藏!
祝大家逢考必过!逢投必中!上岸上岸上岸!upupup
大多数高校硕博生毕业要求需要参加学术会议,发表EI或者SCI检索的学术论文会议论文。详细信息可扫描博文下方二维码 “
学术会议小灵通”或参考学术信息专栏:https://ais.cn/u/mmmiUz
异常检测概论 — 从经典算法到深度学习(含实用 Python 示例)
- 本文系统性地介绍异常检测(anomaly / outlier detection):定义、任务类型、评价指标、经典方法、现代深度学习方法、时序/图/多模态扩展、实战策略与常见问题。
- 每个部分给出直观解释、优缺点与实用建议,并在结尾提供两个可直接运行的 Python 示例(经典方法 + 深度自编码器)。
1. 什么是异常检测(Why & What)
定义:
- 在给定数据集中,找出与大多数样本行为显著不同的样本。异常在不同领域也称离群点、异常样本、故障、入侵、欺诈等。
任务形式:
- 无监督:只有(或主要)正常/未标注数据(最常见)。
- 半监督:训练集中只有正常样本,检测异常为目标(one-class 学习)。
- 有监督:训练数据有异常标签(但通常异常样本稀少且不平衡)。
应用场景:
- 金融欺诈、网络入侵检测、设备故障预警、医疗异常(影像/生理信号)、制造质量检测、时间序列突变检测等。
2. 评估指标(怎么衡量好坏)
异常检测通常是高度不平衡的分类问题,常用指标:
- 精确率 (Precision), 召回率 (Recall), F1-score(对不平衡常用)
- ROC-AUC(对概率评分很常用,但在极端不平衡时可能误导)
- PR-AUC(Precision-Recall 曲线下面积,在稀有异常时更有价值)
- 平均检测时间 / 延迟(实时场景)
- False Positive Rate(工程可容忍范围重要)
实务建议:优先看 Recall@low-FPR 或 PR-AUC,根据业务对误报/漏报的权衡选择阈值。
3. 数据类型与问题细分
- 静态表格数据(宽表):如信用卡交易的特征向量。
- 图像数据:制造缺陷、肿瘤检测。
- 时间序列 / 流式数据:传感器数据、日志、股票数据。
- 图/网络数据:节点异常、边异常(社交网络)。
- 多模态数据:图像+文本+结构化信息。
不同类型数据用不同方法或组合策略。
4. 经典(非深度)方法(直观 + 优/缺点)
4.1 统计方法
- Z-score / IQR / Boxplot:基于单变量分布;简单但不能捕捉复杂关联。
- 高斯模型 / 多元正态(Mahalanobis 距离):对协方差考虑,适合近似高斯的数据;对高维和非高斯分布受限。
- KDE(核密度估计):估计概率密度,低密度处为异常;受维度诅咒。
4.2 距离 / 密度基方法
- kNN distance / LOF (Local Outlier Factor):基于密度局部比较;能检测局部异常,但对大规模数据和高维度慢。
- DBSCAN / 层次聚类异常分支:聚类后小簇或噪声点可视为异常。
4.3 树 / 集成方法
- Isolation Forest:通过随机切分来“隔离”样本,异常更易被隔离,计算效率高,适合高维。常用且鲁棒。
- One-Class SVM:找出将数据包围的超平面(或超球);对复杂分布不够灵活、对核和参数敏感。
4.4 线性降维与子空间方法
- PCA / Robust PCA:用重构误差判断异常(异常样本在主子空间外)。适合线性可表示的数据;对复杂非线性结构有限。
5. 深度学习方法(近年主流 — 对复杂数据尤其有效)
5.1 自编码器 (AE)
- 思想:训练一个压缩-重构网络,正常样本重构误差低,异常高。
- 变体:Denoising AE、Sparse AE、Contractive AE。
- 优点:对图像、序列可直接端到端;可与卷积/LSTM结合。
- 缺点:若训练数据含大量异常,或异常与正常在重构上差异小,效果差。
5.2 变分自编码器 (VAE)
- 给出概率生成模型与重构,使用似然/重构损失 + KL 做评分。善于建模数据分布。
5.3 GAN-based 方法(如 AnoGAN / f-AnoGAN)
- GAN 学习正常数据分布,使用判别器/生成器辅助评分或通过反求 z 重构误差判断异常。训练不稳定,调参复杂。
5.4 对比学习与自监督
- 通过构造预text task(旋转预测、patch-prediction、contrastive tasks)学习表征,再在表征空间做经典检测(kNN、LOF)或在 head 上做一类分类。对少标签与跨域泛化有优势。
5.5 专用架构
- Reconstruction + Forecasting:时序中用预测误差(LSTM预测下一步)作为异常指标。
- 序列到序列自编码器、Transformer-based 检测器:对长序列模式更灵活。
- Graph Neural Networks (GNN):图数据异常检测(节点/边的异常分数)。
5.6 Parameter-efficient / hybrid
- Use pretrained encoders (ImageNet) + apply AE/one-class head; 或用 contrastive pretrained features + simple detector(实践中非常有效)。
6. 时序异常检测(专门技巧)
- 点异常 vs 突变(change point) vs 事件(collective) 区分重要。
- 方法:ARIMA / Prophet(统计预测)/ LSTM autoencoder / Seq2Seq prediction / Transformer forecasting / Matrix profile(SAX/matrix-profile),以及基于滑动窗口的重构或预测误差。
- 关键:考虑季节性、趋势、上下文窗口、延迟容忍度。
7. 实践工作流(工程化)
- 明确异常定义与业务代价(FP vs FN)。
- 数据准备:清洗、缺失值处理、特征工程(时序滑窗、聚合)、归一化。
- 选择基线(IsolationForest、LOF、OneClassSVM、AE)。
- 训练 & 验证:用合成/历史标签与人工标注子集进行评估;做交叉验证或时序分割验证。
- 阈值选择:基于验证集或按照业务策略(固定FPR/固定Recall)。
- 部署监控:在线评分、漂移检测、阈值自适应、重训练策略。
8. 常见挑战与注意点
- 数据稀有与标签稀少:常用无监督或半监督方法 + 人工回顾。
- 类别/概念漂移:模型过时需定期重训练或自适应。
- 高维诅咒:经典密度/核方法失效,需降维或用深表征。
- 评估困难:真实异常稀少,模拟异常可能不真实,需 domain expert。
- 误报成本高:在工业场景中要控制 FPR,可能牺牲部分 Recall。
9. 实战策略(best-practices)
- 先用简单鲁棒的方法(IsolationForest、LOF)做 baseline。
- 若是图像/时序,先用预训练 encoder + 简单 detector(kNN on features 或 AE on features)。
- 使用对比学习/预训练表征+轻量检测器,在小样本/跨域情况下优于直接训练深模型。
- 多模型融合(ensemble)常显著降低误报。
- 设计评价指标贴合业务(例如 Recall@FPR=0.01)。
10. Python 示例(A:经典方法;B:深度自编码器)
- 下面给出两个可运行示例,分别使用 sklearn(经典)和 PyTorch(AE)。运行前确保安装
scikit-learn, torch, torchvision, matplotlib, numpy。
示例 A — 经典方法(合成数据 + IsolationForest / LOF / OneClassSVM)
# Classic methods demo
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.ensemble import IsolationForest
from sklearn.neighbors import LocalOutlierFactor
from sklearn.svm import OneClassSVM# 生成数据:一个正态簇 + 少量异常
X, _ = make_blobs(n_samples=300, centers=[[0,0]], cluster_std=0.6, random_state=0)
rng = np.random.RandomState(42)
n_outliers = 20
outliers = rng.uniform(low=-6, high=6, size=(n_outliers, 2))
X_all = np.vstack([X, outliers])# 方法1: Isolation Forest
iso = IsolationForest(contamination=n_outliers/(len(X_all)), random_state=0).fit(X_all)
scores_iso = -iso.decision_function(X_all) # higher -> more abnormal
pred_iso = iso.predict(X_all) # 1 normal, -1 outlier# 方法2: LOF (returns -1 for outliers)
lof = LocalOutlierFactor(n_neighbors=20, contamination=n_outliers/(len(X_all)))
pred_lof = lof.fit_predict(X_all)
scores_lof = -lof.negative_outlier_factor_# 方法3: OneClassSVM
ocsvm = OneClassSVM(nu=0.05, kernel="rbf", gamma=0.1).fit(X_all)
pred_ocsvm = ocsvm.predict(X_all)
scores_ocsvm = -ocsvm.decision_function(X_all)# 可视化
plt.figure(figsize=(12,4))
for i,(name,pred,scores) in enumerate([("IsolationForest", pred_iso, scores_iso),("LOF", pred_lof, scores_lof),("OneClassSVM", pred_ocsvm, scores_ocsvm),
]):plt.subplot(1,3,i+1)plt.title(name)normals = X_all[pred==1]outs = X_all[pred==-1]plt.scatter(normals[:,0], normals[:,1], s=10, label='normal')plt.scatter(outs[:,0], outs[:,1], color='r', s=20, label='outlier')plt.legend()
plt.tight_layout()
plt.show()
- 说明:IsolationForest 通常在高维与大规模数据中表现稳定;LOF 对局部密度敏感;OneClassSVM 对核/参数敏感。
示例 B — 深度自编码器(PyTorch,基于 MNIST: 将部分数字设为异常)
# AE anomaly detection on MNIST (train on digits 0-4 as 'normal', test includes 5-9 as anomalies)
import torch, torch.nn as nn, torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader, Subset
import numpy as npdevice = torch.device("cuda" if torch.cuda.is_available() else "cpu")# 数据:把 0-4 视为正常,5-9 视为异常(演示用)
transform = transforms.Compose([transforms.ToTensor()])
train_ds = datasets.MNIST(root="data", train=True, download=True, transform=transform)
test_ds = datasets.MNIST(root="data", train=False, download=True, transform=transform)# 训练集只用 labels 0-4
train_idx = [i for i,(x,y) in enumerate(train_ds) if y in range(0,5)]
train_subset = Subset(train_ds, train_idx)
train_loader = DataLoader(train_subset, batch_size=128, shuffle=True, num_workers=2)# 测试集保留全部,用于评估异常分数
test_loader = DataLoader(test_ds, batch_size=256, shuffle=False, num_workers=2)# 简单卷积自编码器
class ConvAE(nn.Module):def __init__(self, zdim=32):super().__init__()self.encoder = nn.Sequential(nn.Conv2d(1, 16, 3, stride=2, padding=1), nn.ReLU(),nn.Conv2d(16, 32, 3, stride=2, padding=1), nn.ReLU(),nn.Flatten(),nn.Linear(32*7*7, zdim))self.decoder = nn.Sequential(nn.Linear(zdim, 32*7*7),nn.Unflatten(1, (32,7,7)),nn.ConvTranspose2d(32,16,3,stride=2,padding=1,output_padding=1), nn.ReLU(),nn.ConvTranspose2d(16,1,3,stride=2,padding=1,output_padding=1), nn.Sigmoid())def forward(self,x):z = self.encoder(x)xrec = self.decoder(z)return xrecmodel = ConvAE().to(device)
opt = optim.Adam(model.parameters(), lr=1e-3)
loss_fn = nn.MSELoss()# 训练
for epoch in range(10):model.train()tot=0for x,y in train_loader:x = x.to(device)xr = model(x)loss = loss_fn(xr, x)opt.zero_grad(); loss.backward(); opt.step()tot += loss.item()*x.size(0)print(f"Epoch {epoch+1}, train_loss={tot/len(train_loader.dataset):.6f}")# 测试:用重构误差作为异常分数
model.eval()
scores=[]; labels=[]
with torch.no_grad():for x,y in test_loader:x = x.to(device)xr = model(x)mse = ((xr-x)**2).view(x.size(0), -1).mean(dim=1).cpu().numpy()scores.append(mse)# label: 0-4 normal -> 0, 5-9 anomaly -> 1labels.append((y.numpy()>=5).astype(int))
scores = np.concatenate(scores)
labels = np.concatenate(labels)# 简单评估:ROC AUC, PR AUC
from sklearn.metrics import roc_auc_score, average_precision_score
print("ROC AUC:", roc_auc_score(labels, scores))
print("PR AUC:", average_precision_score(labels, scores))
- 说明:在实际应用中可以使用更复杂的 AE 变体(VAE、Denoising AE)或结合预训练特征(用 ResNet 的中间特征作为 AE 的输入)以获得更好效果。
11. 进一步阅读 / 常用工具(简短)
- Python 库:
scikit-learn(IsolationForest, OneClassSVM, LOF),pyod(专门异常检测库,包含大量方法),alibi-detect(工业检测工具),deepforest/tensorboard用于监控,tsfresh/ruptures(时序分析 change point)。 - 研究方向:对比学习在无监督异常检测中的应用、基于概率密度的深度生成模型、图异常检测、元学习与少样本异常检测。
12. 小结
- 异常检测是高度场景依赖的问题:没有“万能方法”。
- 工程实践通常从简单、可解释且高效的方法(IsolationForest、LOF、PCA)开始;对复杂数据(图像/序列)逐步引入深度表征(自编码器、VAE、对比学习、Transformer)。
- 评估需贴合业务代价(FP/FN 的不对称成本),并把阈值选择与在线监控纳入设计。
- 实务建议:用预训练表征 + 简单检测器作为 baseline,再尝试专用深模型;使用多模型融合与人类在环(human-in-loop)提高可靠性。
