4. 统计学方法(一):3-Sigma原则、Z-Score方法、箱线图法(IQR)

聊到异常检测,很多人第一反应就是上机器学习模型。但说实话,我做了这么多年实战项目,最常用的反而是最基础的统计学方法。为什么?因为简单、可解释、还特别快。

今天咱们就聊聊三个经典工具:3-Sigma、Z-Score 和箱线图。它们都是基于数据分布来做判断的。说白了,就是看看哪些点「不合群」。

核心思想:异常点就是那些偏离正常分布太远的点。统计学给了我们一把尺子,量一量就知道谁出格了。

4.1 3-Sigma 原则

3-Sigma 原则,也叫拉依达准则。它假设数据服从正态分布。嗯,这里要注意——这个假设很关键。

正态分布有个特性:约 68% 的数据落在均值±1个标准差内,95% 落在±2个标准差内,99.7% 落在±3个标准差内。那剩下的 0.3% 呢?就是咱们要找的异常点。

判断规则很简单:

  • 数据点与均值的距离 > 3倍标准差 → 异常
  • 数据点与均值的距离 ≤ 3倍标准差 → 正常

我在项目中遇到过这样的情况:某传感器采集的温度数据,用 3-Sigma 一筛,发现几个点明显偏离。后来排查发现是传感器接触不良。你看,一个简单的统计规则,直接定位了硬件问题。

避坑指南:我曾经在一个非正态分布的数据集上硬套 3-Sigma,结果误报率高达 30%。后来才意识到,数据偏态严重时,3-Sigma 会失效。所以用之前,先画个直方图看看分布形态。

4.2 Z-Score 方法

Z-Score 其实是 3-Sigma 的标准化版本。它把原始数据转换成标准分数,公式很简单:

Z = (x - μ) / σ

其中 x 是原始值,μ 是均值,σ 是标准差。Z 值表示数据点偏离均值多少个标准差。

判断标准:

  • |Z| > 3 → 异常(对应 3-Sigma)
  • |Z| > 2 → 可疑点,需要关注
  • |Z| ≤ 2 → 正常

你想想看,Z-Score 的好处是什么?它把不同量纲的数据统一到一个尺度上。比如你同时监控温度和压力,温度单位是摄氏度,压力是帕斯卡。直接用原始值没法比,但转成 Z-Score 后,就能放在一起分析了。

我个人习惯在数据预处理阶段先算 Z-Score,然后设定阈值。阈值怎么定?我一般先看业务容忍度。比如金融交易中,|Z|>2 就标记为可疑,因为漏掉一笔欺诈的代价太高了。

小技巧:如果数据量小(比如少于 30 个样本),Z-Score 的可靠性会下降。这时候我建议用箱线图法,它对样本量不敏感。

4.3 箱线图法(IQR)

箱线图法不依赖正态分布假设。它基于四分位数,说白了就是看数据的「中间段」和「两端」的关系。

核心概念:

  • Q1(第一四分位数):数据从小到大排列,25% 位置的值
  • Q3(第三四分位数):数据从小到大排列,75% 位置的值
  • IQR(四分位距):IQR = Q3 - Q1
  • 异常判定:数据点 < Q1 - 1.5×IQR 或 > Q3 + 1.5×IQR

为什么用 1.5 倍?这是统计学前辈们总结的经验值。如果你想要更严格的筛选,可以用 3 倍 IQR。我在做工业质检项目时,就用了 3 倍 IQR,因为产品瑕疵容忍度极低。

箱线图法的优势很明显:

  • 不要求数据服从特定分布
  • 对极端值不敏感(均值会被极端值拉偏,但中位数不会)
  • 可视化直观,一眼就能看出异常点

实战对比:我曾经处理过一组电商订单金额数据,分布严重右偏(大部分订单几十块,偶尔有上万的)。用 3-Sigma 筛,那些上万的大单全被判为异常。但用箱线图法,只有真正离谱的(比如 Q3+3×IQR 之外的)才被标记。哪个更合理?显然是箱线图法。

4.4 三种方法对比

方法 适用场景 优点 缺点
3-Sigma 数据近似正态分布 计算简单,理论成熟 对非正态分布失效
Z-Score 多维度数据标准化后对比 统一量纲,阈值可调 同样依赖正态假设
箱线图法 任意分布,小样本 鲁棒性强,可视化好 对 IQR 倍数选择敏感

4.5 知识体系图

下面这张图帮你理清这三种方法的关系和适用场景:

统计学异常检测方法体系 异常检测目标 3-Sigma 原则 Z-Score 方法 箱线图法 (IQR) 适用:正态分布数据 适用:多维度标准化对比 适用:任意分布、小样本 核心逻辑:计算数据点与「正常范围」的距离,超出阈值即判为异常

4.6 代码实战

光说不练假把式。下面我用 Python 演示这三种方法:

import numpy as np
import pandas as pd

# 生成示例数据(包含异常点)
np.random.seed(42)
data = np.random.normal(100, 15, 1000)
data = np.append(data, [200, 210, 50, 45])  # 加入4个异常点

# 方法1:3-Sigma
mean = np.mean(data)
std = np.std(data)
sigma_3_upper = mean + 3 * std
sigma_3_lower = mean - 3 * std
anomalies_3sigma = data[(data > sigma_3_upper) | (data < sigma_3_lower)]

# 方法2:Z-Score
z_scores = (data - mean) / std
anomalies_zscore = data[np.abs(z_scores) > 3]

# 方法3:箱线图法(IQR)
Q1 = np.percentile(data, 25)
Q3 = np.percentile(data, 75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
anomalies_iqr = data[(data < lower_bound) | (data > upper_bound)]

print(f"3-Sigma 发现异常点: {len(anomalies_3sigma)} 个")
print(f"Z-Score 发现异常点: {len(anomalies_zscore)} 个")
print(f"箱线图法发现异常点: {len(anomalies_iqr)} 个")

我的建议:实际项目中,别只用一种方法。我通常先用箱线图法做快速筛查,再用 Z-Score 做精细分析。两种方法结果一致的点,基本可以确定是异常。如果结果不一致,那就需要结合业务逻辑来判断了。

好了,这三种方法讲完了。它们虽然基础,但非常实用。下次遇到异常检测问题,别急着上深度学习,先试试这些统计方法——说不定就够用了。

专注资料整理