第4章 无监督异常检测(一):统计学方法 — Z-score、IQR、箱线图

统计学方法,是异常检测里最经典的一类。说白了,就是拿数学公式去量每个点“有多离谱”。我早期做金融风控的时候,第一个落地项目用的就是 Z-score,简单、快、解释性强。这章咱们把三个最常用的工具过一遍:Z-score、IQR 和箱线图。

4.1 Z-score — 标准分数抓离群点

Z-score 的核心思路:看一个点到均值的距离,比上标准差。公式长这样:

Z = (x - μ) / σ

其中 μ 是均值,σ 是标准差。Z 的值越大,说明这个点越“特立独行”。通常阈值取 3,即 |Z| > 3 判定为异常。

举个例子:一组客户交易金额,均值 500,标准差 100。某笔交易 1200,Z = (1200-500)/100 = 7 > 3,妥妥异常。

我的习惯:阈值不一定要死盯 3。如果数据噪声大,我会放宽到 3.5;如果要求灵敏,2.5 也行。最好结合业务容忍度调一调。

但 Z-score 有个大坑——它对均值、标准差本身敏感。如果异常点本身已经把均值拉偏了,那 Z-score 就会漏检。我以前在电商销量监控里就吃过这个亏。

4.2 IQR — 四分位距的鲁棒方案

IQR 不依赖均值和标准差,它用中位数和四分位数。公式:

IQR = Q3 - Q1
下界 = Q1 - 1.5 * IQR
上界 = Q3 + 1.5 * IQR

超出上下界的,判为异常。系数 1.5 是 Tukey 老爷子定的经典值。可以用 3 倍做极端离群点。

为什么 IQR 更鲁棒?因为中位数和四分位数不怕极端值干扰。我做过一个传感器数据清洗项目,传感器偶尔飘高,均值被拉上天,Z-score 全废。换成 IQR 后,瞬间稳了。

对比一张表:
方法对异常敏感假设分布计算量适用场景
Z-score高近似正态低数据无偏、量纲统一
IQR低(鲁棒)任意连续低含离群点、分布偏态
我踩过的坑:我曾经在处理网络流量数据时,直接用 IQR 的 1.5 倍,结果正常突发的尖峰全被标成异常,误报率高得离谱。后来才发现,那个流量分布是长尾的,1.5 倍太紧。换成 3 倍才平衡好。

4.3 箱线图 — 可视化你的异常

箱线图是 IQR 的图形化表达。盒子从 Q1 到 Q3,中间线是中位数,胡子延伸到上下界之外的点就是异常。

我通常把箱线图当作探索性分析的快照。拿到新数据,先画箱线图扫一眼,能看到:

  • 哪些变量离群点多
  • 分布是否对称
  • 有没有极端值拖拽均值

箱线图虽然直观,但阈值是固定的(1.5×IQR)。不能灵活适应业务场景。所以我会在建模前用它做“初筛”,上线时还是用动态阈值。

4.4 三种方法联合诊断流程

在实际项目中,我不会只依赖一种方法。我会这样做:

  1. 先用箱线图全量扫一遍 —— 可视化看分布形态和异常点位置
  2. 对可疑点算 Z-score —— 看偏了多少个标准差
  3. 用 IQR 验证异常边界 —— 避免均值被污染影响判断
  4. 业务确认+标记 —— 最终异常由人做决策

这样组合下来,误报率比单用任何一种都低。我管这叫“三保险”。

一个小经验:如果数据量很大(百万级以上),箱线图绘制会慢,这时我直接算 IQR 上下界,然后做条件筛选。箱线图只针对抽样样本可视化。

好,这张图把核心逻辑串起来了:

统计学异常检测方法联合流程 原始数据 箱线图初筛 Z-score验证 IQR边界 业务确认 初筛看分布形态 Z-score看偏离度 IQR定边界

4.5 代码速写 — Python 实现

动手跑一下,感觉就来了。下面这个例子,我刻意混入了一个异常值:

import numpy as np
import pandas as pd

# 生成数据:正态分布 + 1个异常
np.random.seed(42)
data = np.random.normal(50, 10, 100)
data = np.append(data, 150)  # 异常值

# Z-score
mean = np.mean(data)
std = np.std(data)
z_scores = (data - mean) / std
outliers_z = data[np.abs(z_scores) > 3]
print("Z-score 异常:", outliers_z)

# IQR
Q1 = np.percentile(data, 25)
Q3 = np.percentile(data, 75)
iqr = Q3 - Q1
lower = Q1 - 1.5 * iqr
upper = Q3 + 1.5 * iqr
outliers_iqr = data[(data < lower) | (data > upper)]
print("IQR 异常:", outliers_iqr)

跑一下你会发现,Z-score 和 IQR 都能抓到 150 这个异常。但如果再多几个离群点,IQR 往往更稳定。我自己跑生产数据时,偏爱 IQR 做第一道防线。

4.6 优缺点总结

方法优点缺点
Z-score计算快、直观、有统计理论支撑对非正态分布不友好、均值易被污染
IQR鲁棒、不依赖分布、实现简单阈值固定(1.5×IQR)、无法自适应
箱线图可视化易懂、便于探索无法自动化、大数据量慢
认真提醒:统计学方法虽然快,但处理高维、非线性、复杂分布数据时,会严重失效。比如图像像素异常、加密流量检测,基本用不了。这章只是起点。

嗯,这一块的内容先到这。多动手调一下阈值参数,你会对数据分布有更深的体感。