4. 异常检测算法:3-Sigma法则、MAD、IQR与Z-Score变体

阈值设好了,但数据一变,阈值就成了摆设。这是我在很多项目里反复踩过的坑。静态阈值就像刻舟求剑,数据分布一偏移,告警要么炸锅,要么装死。所以这一章,我们来聊聊真正能“动起来”的异常检测算法。

说白了,这些算法就是帮我们回答一个问题:当前这个数据点,到底正不正常? 我个人的习惯是,先搞清楚数据的分布形态,再选算法。下面这四种,是我在生产环境里用得最多的。

核心思路: 异常检测不是玄学,它是基于统计学的“离群点”识别。你选哪种算法,取决于你的数据长什么样。

4.1 3-Sigma法则:最经典,但最挑数据

3-Sigma 法则,也叫拉依达准则。它的逻辑很简单:如果数据服从正态分布,那么 99.7% 的数据会落在均值 ±3 个标准差之内。落在外面?那就是异常。

公式长这样:

阈值上限 = μ + 3σ
阈值下限 = μ - 3σ

我在项目中遇到过一个问题:某业务的响应时间,平时很稳定,但偶尔会有几个超大的毛刺。用 3-Sigma 去抓,效果很好。但一旦业务大促,流量暴增,均值 μ 和标准差 σ 被瞬间拉高,阈值就跟着“飘”了,导致大量正常请求被误告。

避坑指南: 3-Sigma 对异常值本身非常敏感。如果数据里已经混入了大量异常,算出来的 μ 和 σ 本身就是错的。我曾经在一个被爬虫攻击的系统上直接用 3-Sigma,结果阈值被异常值“带偏”,正常流量反而被误杀。所以,用之前一定要先做数据清洗。

4.2 MAD(中位数偏差):抗干扰的硬汉

3-Sigma 太“娇气”了,受不了异常值的污染。那怎么办?用中位数代替均值,用 MAD 代替标准差。这就是 MAD 算法的核心思想。

MAD 的计算分三步:

  1. 计算数据的中位数(Median)。
  2. 计算每个数据点与中位数的偏差:|xᵢ - Median|。
  3. 取这些偏差的中位数,就是 MAD。

阈值公式:

阈值上限 = Median + k * MAD
阈值下限 = Median - k * MAD
// k 通常取 3,但可以根据业务敏感度调整

你想想看,中位数不受极端值影响,MAD 也不受极端值影响。所以这套组合拳,对异常值的“免疫力”非常强。我个人习惯在监控 CPU 使用率、内存占用这类指标时,优先用 MAD。因为这些指标经常会有瞬间的毛刺,但整体趋势是稳定的。

小技巧: 如果数据分布比较对称,k 取 2.5~3.5 效果都不错。如果数据偏态严重,建议把 k 调大一点,比如 4~5,避免误报。

4.3 IQR(四分位距):箱线图的灵魂

IQR 大家应该不陌生,箱线图就是靠它画的。它的原理是把数据切成四份,看中间 50% 数据的跨度。

计算步骤:

  1. 找到下四分位数 Q1(25% 分位)和上四分位数 Q3(75% 分位)。
  2. IQR = Q3 - Q1。
  3. 阈值:下限 = Q1 - 1.5 * IQR,上限 = Q3 + 1.5 * IQR。

这里的 1.5 是经验值,对应正态分布下大约 0.7% 的异常概率。如果你觉得告警太敏感,可以改成 3。我在做日志错误率监控时,就喜欢用 IQR。因为日志错误率经常是“大部分时间很低,偶尔飙高”,用 IQR 能很好地抓住那些真正的异常尖刺。

算法 对异常值敏感度 适用数据分布 计算开销
3-Sigma 高 正态分布 低
MAD 低 对称分布,有毛刺 中
IQR 低 偏态分布,有离群点 中

4.4 Z-Score 变体:给数据打个分

Z-Score 本身不是阈值算法,它是一个“标准化”工具。它告诉你一个数据点距离均值有多少个标准差。但我们可以把它改造成异常检测器。

标准 Z-Score:

Z = (x - μ) / σ

如果 |Z| > 3,就认为是异常。但问题又回到了 3-Sigma 的老路上——μ 和 σ 容易被污染。所以,我推荐用它的变体:修正 Z-Score。

修正 Z-Score 用中位数和 MAD 代替均值和标准差:

修正 Z = 0.6745 * (x - Median) / MAD

这里的 0.6745 是一个常数,目的是让修正 Z-Score 在正态分布下与标准 Z-Score 尺度一致。当 |修正 Z| > 3.5 时,就可以判定为异常。

嗯,这里要注意:修正 Z-Score 比标准 Z-Score 稳健得多。我在做全链路监控的“黄金指标”(延迟、流量、错误、饱和度)异常检测时,底层用的就是修正 Z-Score。它既能抵抗毛刺,又能保持对真实异常的敏感度。

我的选择建议:
  • 数据干净、正态分布 → 3-Sigma(简单高效)
  • 数据有毛刺、但整体对称 → MAD 或 修正 Z-Score
  • 数据偏态、有离群点 → IQR
  • 需要标准化打分 → 修正 Z-Score

4.5 算法选择框架图

下面这张图,是我自己总结的算法选择流程。每次做新业务的阈值调优,我都会先走一遍这个决策树。

异常检测算法选择决策树 异常检测算法选择决策树 原始数据 数据是否近似正态分布? 是 → 3-Sigma 否 → 继续判断 数据是否有大量毛刺? 是 → MAD / 修正Z-Score 否 → IQR 💡 说明: • 3-Sigma 适合数据干净、正态分布的场景,计算最快。 • MAD 和修正 Z-Score 抗毛刺能力强,适合生产环境。 • IQR 对偏态分布友好,适合日志、错误率等指标。

4.6 实战中的避坑与调优

算法选好了,不代表就万事大吉了。我在实际落地时,还遇到过几个坑:

  • 窗口大小怎么定? 这些算法都需要一个滑动窗口来计算统计量。窗口太小,阈值抖动太厉害;窗口太大,对突变的响应太慢。我一般建议窗口大小是业务周期的 2~3 倍。比如业务有日周期,窗口就设 2~3 天。
  • 冷启动怎么办? 新业务上线,数据不够。我的做法是先给一个保守的静态阈值兜底,等积累了 1000 个以上的数据点,再切换到动态算法。
  • 阈值要不要平滑? 直接算出来的阈值,可能会因为数据抖动而忽高忽低。我习惯对阈值本身做一次指数移动平均(EMA),让阈值变化更平滑。
我的经验: 不要迷信任何一种算法。在生产环境里,我经常是“多算法投票”。比如同时跑 MAD 和 IQR,两个都告警才触发,能有效降低误报率。