拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

异常值检测方法详解:从统计检验到机器学习的20种实用方案

异常值检测方法详解:从统计检验到机器学习的20种实用方案

做数据分析的人,十有八九都经历过这种场景:指标算出来,均值方差总觉得哪里不对劲,画个箱线图一看,几个点孤零零甩在尾巴上。把它删了吧,怕把真实信号删没了;留着吧,模型被它拽得东倒西歪。异常值检测这个事,表面看是"找不正常的数",实际操作里全是门道。方法选错、假设不成立、尺度不统一,都会让结果南辕北辙。

这篇文章我按"统计检验派、距离残差派、密度聚类派、高维时序派"四条线,把常见的20种数据异常值检验方法从头到尾捋一遍。每种方法都写了原理、适用条件、核心代码和实际坑点,最后再给一张速查表和选型流程。不管你是刚入行的数据新人,还是被脏数据折磨已久的老手,都能按图索骥找到适合当前场景的那把刀。

1. 动检之前,先把这几个问题想清楚

1.1 重新定义"异常值"

很多人一上来就套公式,结果常栽在第一步:对"异常"的理解本身就歪了。同一批数据,在不同语境下"异常"的定义完全不同。

按统计学的经典定义,异常值是"明显偏离其余观测值的观测值",但这个"明显偏离"依赖你对数据分布的假设。如果数据近似正态,那偏离均值3倍标准差以上就是极端;如果数据是长尾分布,尾巴上的点可能完全正常。更细一点,还能把异常分成三种:

  • 全局异常:单看一个点,它就和绝大多数样本不一样,比如一批订单金额里混进一个一百万的。
  • 局部异常:放在全局看挺正常,但放在它所在的局部邻域里很反常。比如商场工作日下午人流量都是300-500,突然有个店面单小时冲到3000。
  • 时序异常:在时间上下文里才体现出来。比如服务器QPS平时波动平稳,某天凌晨3点突然翻十倍,放在全局统计里可能只是尾巴,但在时间序列里就是明确异常。

动手检测前先问自己:我要的是哪种异常?这决定了下面20种方法里哪几种适用。

1.2 数据分布假设比方法本身更重要

异常值检验方法几乎都自带前提假设。3σ原则要求近似正态,Grubbs检验直接要求正态总体,IQR不要求分布但要求样本量别太小,LOF这类基于密度的方法对数据尺度极度敏感。假设不满足,再"高级"的方法也只是精确地给出错误答案。

所以在正式检测前,我强烈建议先做三件事:看直方图了解分布形状,做正态性检验(Shapiro-Wilk或者K-S检验)确认能不能用参数方法,画散点图看数据有没有明显的簇结构和局部密度差异。这一步不花多少时间,但能帮你避掉后面一大半坑。

1.3 检出异常以后怎么办

检测本身不是终点。拿到异常值清单后,通常会走四条路之一:

  • 删除:确认是采集错误、录入错误或测量故障,直接剔除。
  • 截尾/替换:用分位数、均值或前后值把异常拉回归一范围,常用在时间序列和评分卡里。
  • 保留但稳健化:数据本身就在长尾分布上,此时不该删点,而应该用中位数、MAD、稳健回归这类方法降低极值影响。
  • 单独建模:异常本身代表风险或机会,比如反欺诈、故障预警,这时候异常值恰恰是最需要分析的信号。

这个方法库里所有技术,最终都是为上面某一种策略服务的。先定策略,再选方法,顺序不要反。

2. 统计检验派:经典且上手的8种方法

2.1 3σ原则与Z-score

3σ原则是新手最容易接触到的异常检测方法,核心假设是数据近似服从正态分布。计算每个点离均值的标准差倍数:

z = (x - μ) / σ

当|z| > 3时,该点落在均值±3σ之外,在标准正态分布下概率只有约0.27%,判定为异常。

优点是好算、好解释,业务方一听就懂。缺点有二:其一是均值和标准差本身对异常值敏感,如果数据里已经混入好几个异常点,均值和σ会被"污染"得偏大,导致异常点被掩盖(统计上叫masking效应),本来很极端的点反而算不出高z值;其二是真实业务数据很少是干净的正态分布,稍微带点偏态就很容易误杀。

所以3σ最适用的场景是:质量管理里对单指标的粗筛、数据采集阶段的快速体检、特征分布相对受控的工业传感数据。用在偏斜严重的收入、流量数据上,要非常小心。

2.2 MAD中位数绝对偏差法

为了对抗3σ对异常值敏感的问题,统计学家推荐用中位数和MAD来替代均值和标准差。MAD计算方式是:

MAD = median(|Xi - median(X)|)

为了让它能和标准差在同尺度上比较,通常乘一个修正系数1.4826(在正态分布下,MAD约等于0.6745σ,所以取倒数)。改进后的稳健Z-score为:

z_mad = 0.6745 * (Xi - median(X)) / MAD

|z_mad| > 3.5时可判为可疑异常值,这个阈值是Iglewicz和Hoaglin在1993年论文里给出的建议。

MAD法的好处是抗遮盖能力强,即使数据里混入20%左右的异常值,中位数和MAD的估计也不会被明显拉偏。对于偏态数据、含较多离群点的数据,它比3σ可靠得多。我在处理用户行为指标时,默认就会先用MAD扫一遍,再决定要不要用更复杂的方法。

2.3 IQR四分位距法

这是箱线图背后的原理,也是我日常用得最频繁的快速体检方法。先把数据按大小排序,取第一四分位数Q1(25%分位)和第三四分位数Q3(75%分位),定义四分位距:

IQR = Q3 - Q1

常规判异常的下限是Q1 - 1.5IQR,上限是Q3 + 1.5IQR。超出这个区间的点,在箱线图里会显示为箱体外的散点。如果想更激进地筛选极端值,可以用3倍IQR作为界限。

IQR不依赖数据分布,天然对异常值稳健,因为分位数不受极端值影响,但它也有一个隐性前提:样本量不能太小。数据只有几十个时,IQR本身波动就大,用1.5倍界外很容易误判。另外对厚尾分布,Q1和Q3之间的距离被极值撑得很大,很多真正的异常反而落在"正常范围"里。这时候可以考虑对数据取对数,或者用广义ESD方法。

2.4 Grubbs检验

Grubbs检验(也叫广义极端学生化偏差检验中的单点版本)是假设检验派的代表,专门用来检测"正态样本中是否存在一个离群点"。原假设是数据没有离群值,统计量是:

G = max|Xi - mean| / sd

也就是离均值最远的那个点,距离用标准差标准化后有多大。拿到G值后,根据样本量n和显著性水平α查临界值,超过临界值就拒绝原假设,认为最大值或最小值是异常。

Grubbs检验有明确的统计推断意义,不像3σ那样拍脑袋。但它有两个明显限制:一次只能检验一个离群点,而且对masking效应敏感——数据里有多个异常时,方差被拉大,G值会变小,导致检不出来。所以用它时要先对数据做仔细的可视化检查,确认异常点数量不超过1个,或者在每轮剔除一个异常后重复检验。

这个检验在R里有outliers::grubbs.test,Python里可以自己写,核心逻辑就是计算G值和临界值。样本量小时(n<30)它比3σ可靠得多,因为临界值会根据样本量自动收紧。

2.5 Dixon检验

Dixon检验也叫Q检验,Grubbs检验同属小样本异常检测的经典方法,最早用于化学实验中可疑测量值的判断。它把极差比作为统计量,专门检验最大值或最小值是不是离群点。

检验最小值时:

Q = (X2 - X1) / (Xn - X1)

其中X1是最小值,X2是第二小值,Xn是最大值。Q值本质上是"最边缘点和次边缘点的差距"占"全数据极差"的比例。这个比值越大,说明最小值和它邻居之间的缝隙越大,越可能是异常。

Dixon检验最突出的价值在于适合小样本,n在3到30之间时很稳。它也不要求估计均值和方差,只依赖排序后的两端数值,所以抗污染能力也不错。缺点是同样一次只能处理一个异常点,检验前可以先用可视化确认异常是否集中在单侧。化学、医学检验这类样本量小、测量过程重复性强的场景,Q检验依然很常用。

2.6 GESD广义极端学生化偏差检验

如果异常点不止一个,又想做严格的假设检验,GESD是首选。它本质上是Grubbs检验的推广,由Rosner提出,专门解决单点Grubbs方法无法处理多异常值的问题。

GESD限制用户设定一个最大可疑异常数r,然后迭代计算。第一轮计算离均值最远的点的标准分数R1,暂时剔除它;第二轮在剩余数据上再算最远点的标准分数R2,再剔除;如此反复,得到R1, R2, ..., Rr。每一轮都有一个对应临界值λi,最后一个满足Ri > λi的序号i,就是建议检出的异常数量。

这套流程能有效规避masking和swamping(正常点被误判为异常)这两个经典问题。我测过故意混入3个异常点的数据,GESD能稳定识别出来,而直接对全量数据跑Grubbs基本检不出。它在Python里没有现成打包好的通用实现,但核心循环不到二十行,Annaconda生态下可以直接参考Rosner的原始论文复现。

2.7 偏度-峰度法与Jarque-Bera检验

偏度(skewness)反映分布不对称的程度,峰度(kurtosis)反映尾部厚度。标准正态分布的偏度为0,峰度为3。如果一个数据集里存在异常极端值,数据分布往往表现为偏度绝对值变大、峰度明显超过3——尾巴变重了,或者出现单侧拖尾。

Jarque-Bera检验就是同时考察这两个指标的统计量:

JB = n * (S² / 6 + (K - 3)² / 24)

S是样本偏度,K是样本峰度。JB值越大,说明数据越偏离正态,原假设"数据来自正态分布"越可能被拒绝。

说到底这个方法不是直接给异常值名单,而是告诉你"这批数据里大概率混杂了异常或重尾成分,别直接套均值、别直接用3σ"。它更像一个预警信号:当看到JB检验P值极小时,就该换稳健方法了。在实际流程里,我把JB检验放在Grubbs、GESD之前做预筛选,很有用。

2.8 正态性检验辅助异常识别

严格说Shapiro-Wilk和Kolmogorov-Smirnov是正态性检验,不是异常值检验,但在业务实操里它们经常被拿来配合异常检测。一个很典型的思路是:对全量数据做正态性检验,P值显著时先不急着下结论,把可视化发现的几个极端点剔除后,再对剩余数据做一次检验。如果P值从不显著变为显著、分布恢复正常,那被剔除的点大概率就是异常。

Shapiro-Wilk适合样本量小于5000的情况,敏感性比较强;大样本下常用K-S检验或者Anderson-Darling检验。这个方法的作用机制是:正态性检验没通过,不代表一定有异常,也可能是分布本身不对称;但配合业务规则和可视化,它能帮你把"纯统计异常"和"分布本来就长这样"区分开。

3. 距离与残差派:把异常放进模型里看

3.1 学生化删除残差与Cook距离

当数据里有解释变量和被解释变量时,单独看一个维度的分布不够,要看"模型预测值和真实值之间的差距"。线性回归有个假设是残差服从正态分布,如果某个样本的残差异常大,它很可能就是异常值。

这里推荐学生化删除残差(studentized deleted residual)。它比普通残差更严格:拟合回归时把第i个样本剔掉,再用剩余样本的模型预测第i个样本,然后计算预测误差并标准化。如果这个值的绝对值超过2或3(根据样本量查t分布临界值),说明这个点对模型的偏离是真实存在的,不是被其他异常样本撑出来的。

与之配套的是Cook距离,它衡量"删除第i个样本后,所有拟合值的变化总量"。Cook距离大的点不一定残差大,也可能是高杠杆点——位置很边缘,对模型影响极大。常规建议是Cook距离大于4/(n-k-1)的样本值得高度警惕。

这个派系特别适合回归建模前的数据清洗,比如广告投放归因、价格弹性分析,直接看指标异常不如看模型残差异常来得准。

3.2 马氏距离

马氏距离是经典统计里处理多维异常最优雅的方法之一。普通欧氏距离不关注变量之间的相关性和量纲差异,而马氏距离把协方差结构考虑进去了:

D_M = sqrt((x - μ)ᵀ Σ⁻¹ (x - μ))

其中Σ是样本协方差矩阵。它能识别出"单变量看起来正常,但组合起来极其异常"的点。举个例子,身高和体重的组合,普通欧氏距离只看到数值差,马氏距离会同时惩罚与整体分布不一致的变量组合。

马氏距离的理想情况是数据服从多元正态分布,此时D²服从卡方分布,可以用卡方临界值(比如自由度p=5时,95%分位对应约11.07)判断异常。实际使用中要注意两个问题:一是协方差矩阵对异常值敏感,高维大样本时可以用最小协方差行列式(MCD)这类稳健估计替代;二是维度太高时协方差矩阵可能病态,需要先用PCA降维。

3.3 KNN距离法

基于距离的异常检测有一个直观思路:如果某个样本和它的k个最近邻居之间的距离都很大,那它就是异常点。KNN距离法用每个点到第k近邻居的距离作为异常分数,这个距离越大,样本越孤立。

实现时通常对距离做标准化,或者取k个邻居的平均距离,避免单一邻居造成波动。k的选择很关键:太小容易被局部噪声欺骗,太大会忽略局部密度差异。我一般建议k取总样本量的2%-5%,并且至少5个以上。

KNN距离法的优点是不需要分布假设,对任何连续型数据都能用;缺点是对数据尺度极度敏感,特征量纲不一致时需要先做标准化。而且它的计算复杂度高,样本量大时要考虑用近似最近邻算法加速。它在欺诈检测、日志异常里很常见,本质上是把"离群程度"转化成"邻居距离"。

3.4 稳健回归残差

普通最小二乘回归本身对异常值很脆弱,一个异常点就能把拟合线拉过去,导致残差看起来都不大。此时异常值反而"藏"进模型里了。要避免这个情况,可以换稳健回归方法,比如Huber回归或RANSAC。

Huber回归通过分段损失函数降低大残差样本的权重:残差小的时候用平方损失,残差大的时候用线性损失,这样异常样本不会过分主导模型。拟合完毕后,再计算每个样本的标准化残差,把残差超过某个阈值(比如3倍稳健标准差)的点标为异常值。

RANSAC的思路更彻底:随机抽样拟合模型,统计每个模型的支持样本数(内点数量),最后保留能获得最多内点支持的模型,不在内点集里的样本视为异常。这套方法在点云注册、计算机视觉、传感器数据融合里用得很多,因为真实世界数据里异常比例可能高得离谱(超过50%),普通稳健回归也扛不住。

4. 密度、聚类与集成派:复杂分布下的主力方法

4.1 LOF局部异常因子

这是局部异常检测的地基方法,由Breunig等人在2000年提出。核心思想是:一个点的异常程度,应该和它邻居的密度对比来看,而不是和全局比。

算法先计算每个点的k距离和k邻域,再计算局部可达密度。如果一个点的局部密度远低于它邻居的局部密度,LOF值就会明显大于1。这就是"局部异常":放全局可能普通,但和周围环境比就突兀。比如闹市区一个高档餐厅,消费金额放在全市看正常,放在那一条小吃街里就是异常异常。

LOF最大的优点是能处理密度不均匀的数据,比如不同区域有不同密度簇时。缺点有两个:一是k值对结果敏感,太小或者太大都会失真;二是计算成本高,不适合超大样本。工程上跑LOF前都会做降维或抽样,或者用FastABOD等近似方法。

4.2 DBSCAN的噪声点

DBSCAN是一种基于密度的聚类算法,它的副产品正好可以用来做异常检测。算法用两个参数扫描数据:邻域半径eps和最小样本数minPts。如果一个点eps半径范围内的邻居数少于minPts,且它自己也不在某个密度可达的簇里,这个点就被标记为噪声点(cluster label为-1)。

DBSCAN做异常检测的好处是完全不用事先指定异常比例,也不用假设数据分布在某个特定形状里,能处理任意形状的簇。但eps参数很难调——设小了全是噪声,设大了把异常点和正常点揉进同一个簇。实际调参时我会先看k距离图(每个点到第minPts近邻居的距离排序曲线),找曲线上出现明显"拐点"的位置作为eps候选值。

4.3 K-means距离法

K-means本质是聚类,但离群检测也很常见。流程是:先用K-means把数据聚成K簇,计算每个样本到其所属簇中心的距离,把距离超过阈值的样本判为异常。更稳健的做法是同时记录每个样本到最近两个簇中心的距离,如果到最近簇的距离大,且到第二近簇的距离也不小,说明它处在簇与簇之间空旷区域,是典型的边界异常。

K-means距离法的优点是简单可扩展,大数据量上跑得飞快,甚至能在Spark或SQL里实现。缺点也很明显:K值要事先给定,簇中心容易被异常点拉偏;而且K-means假设簇是凸形的,数据形状复杂时效果会打折。它比较适合作为高维业务指标的粗筛,不适合精细的局部异常发现。

在距离异常检测场景下,K-means对异常点本身也敏感,所以有时候会先用"k-medoids"这类更稳健的方法,或者刻意设置较大的K值,把异常点单独劈成小簇,再结合每簇样本数判断。

4.4 One-Class SVM

One-Class SVM是支持向量机家族里专门处理单分类问题的模型。它的思路是:不关心正常样本具体属于哪几类,只看正常样本在特征空间里被一个超平面包裹得有多紧,落在超平面之外的样本就是异常。

核函数的选择对One-Class SVM影响极大。RBF核是通行的默认选择,但gamma参数如果太大,每个正常样本都被自己周边的极小区间包住,测试时几乎所有样本都会判为异常;gamma太小,超平面过于平滑,异常点容易漏掉。nu参数控制训练集里"被视为异常"的样本比例上限,相当于给模型一个可容忍的污染率上界。

One-Class SVM在小样本、特征维度不太高的场景下表现很好,比如设备状态监控、单用户行为画像。但训练到大样本时速度慢,调参也有点看手感,不如孤立森林这类方法省心。

4.5 孤立森林

这是集成学习里对异常检测最友好的方法,由刘飞等人提出,核心思想非常反直觉:不描述"正常长什么样",而是用"容易被隔离"来定义异常。

算法随机选一个特征,在特征取值范围内随机选一个切分点,把数据切成两份,递归切下去直到每个样本被单独隔离。正常样本通常要切很多刀才能被孤立出来,异常样本由于分布在稀疏区域,往往几刀就孤立了。每个样本的路径长度均值越小,被孤立得越快,异常分数越高。因为用的是随机切分,它天然不依赖距离计算,非常适合高维大力数据。

sklearn里一行代码就能跑:

from sklearn.ensemble import IsolationForest clf = IsolationForest(contamination=0.05, random_state=42) preds = clf.fit_predict(X) # -1 表示异常

contamination参数表示预估的异常比例,需要结合业务判断并反复验证,这直接决定判定阈值。孤立森林的缺点是对"局部异常"不敏感,因为它是全局的隔离过程,当数据存在明显密度差异时,容易把低密度区域的正常样本判为异常,或者忽略高密度区域里的局部离群点。

5. 高维与时序场景的进阶武器

5.1 PCA重构误差

高维数据里,异常值经常藏在变量之间的相关结构背后。PCA把原始数据投影到几个主成分方向,保留主要方差,再重构回原空间。如果某个样本只符合"大部分变量的正常模式"但违反了变量间的相关关系,它的重构误差(原始向量与重构向量的距离)就会很大。

我举个例子:正常用户在平台上的登录次数和订单金额通常有一定正相关,PCA捕获这个结构后,某个用户登录很多次但订单为零,重构回去时它的误差就会暴露出来。单看每个维度的z-score,这个用户完全正常。

PCA重构误差的实操要点是选主成分个数,通常保留累计方差贡献率85%-90%或者按特征值大于1来选。主成分太少会丢失细节,太多又把噪声学进去。这个方法的天然优势是对线性结构的数据效果极好,且计算高效;缺点是对非线性关系无能为力,这时候要上自编码器。

5.2 自编码器重构误差

自编码器可以看作PCA的非线性版本。网络结构上先通过编码器把输入压缩到低维隐向量,再用解码器从隐向量还原输入。训练时只用正常样本,让重构误差尽量小。检测时如果某个样本重构出来的结果和原样本差得特别远,说明它不符合训练集里"正常样本"的压缩规律,判为异常。

代码大致长这样(PyTorch风格的思想版):

# 训练阶段:只喂正常样本,最小化重构误差 recon = decoder(encoder(x)) loss = mse(recon, x) # 检测阶段:计算每个样本的重构误差,超过阈值判为异常 score = mse(decoder(encoder(x_test)), x_test)

自编码器对图像、文本Embedding、工业传感这类高维非结构化数据的异常检测效果很好。但它也有明显的坑:阈值不好定;如果异常样本混进训练集,模型会把异常也学进去,重构误差反而变小。所以实际项目里要先做一轮保守清洗,或者用更鲁棒的变体(比如对抗自编码器)。网络结构太小学不到正常模式,太大容易过拟合到噪声上,需要结合验证集慢慢调。

5.3 CUSUM与滑动窗口

时间序列异常和普通表格数据不同,它带有时序依赖,不能简单把所有点混在一起算分布。CUSUM(累积和检验)是一种经典的变点检测方法,专门监控序列的均值是否发生持续偏移。它对小幅连续漂移非常敏感,适合检测"缓慢劣化"类的异常。

基本思路是:对每个新观测值,累积它与目标均值的偏差,当累积和超过设定阈值H时报警。实现里通常定义正负两个累积量,分别检测均值上偏和下偏:

S_plus = max(0, S_plus + (x - (μ0 + K))) S_minus = max(0, S_minus - (x - (μ0 - K)))

其中μ0是目标均值,K是允许的偏移灵敏度,H是报警阈值。K通常取δ/2(δ为最小可检测偏移),H取4σ或5σ。这个"允许小幅波动、累积越界才报警"的特性,让它非常适用于工业过程控制、服务器指标监控。

滑窗法更朴素一些:设定一个时间窗口,窗口内计算均值、方差或分位数,如果当前点的值与窗口统计量偏差过大就报警。它比CUSUM更适合检测突发尖峰,但窗口长度要调,太短会被噪声频繁触发,太长又拖慢反应速度。

6. 20种方法速查与选型心法

6.1 方法速查表

方法所属派别关键假设适用场景主要注意点
3σ / Z-score统计近似正态单变量快速体检均值和σ易被污染
MAD改进Z-score统计对称分布即可正态性弱、含多异常阈值3.5为经验值
IQR四分位距统计无明显分布,样本量够箱线图快筛厚尾分布易漏判
Grubbs检验统计正态总体单异常点、小样本多异常时失效
Dixon检验统计正态总体小样本极值检验一次只检一个点
GESD检验统计近似正态多异常点识别需设最大可疑数r
偏度-峰度法/JB检验统计正态对照分布形状预警不给异常名单
正态性检验辅助统计大样本近似配合可视化不是直接方法
学生化删除残差模型残差回归模型正确回归建模前清洗要逐个剔除计算
Cook距离模型残差回归模型正确找高影响点高杠杆≠异常
马氏距离距离多元正态多变量组合异常高维协方差不稳定
KNN距离距离尺度标准一致无分布假设通用检测计算成本高
稳健回归残差模型残差异常比例不太极端数据污染率高需要调损失函数
LOF密度局部密度相近密度不均数据k值难调
DBSCAN聚类密度可分任意形状聚类eps参数敏感
K-means距离聚类簇形状凸大规模数据粗筛K值要定
One-Class SVM边界核函数合适高维小样本调参成本高
孤立森林集成异常易被隔离高维大数据局部异常不敏感
PCA重构误差高维结构线性相关结构变量相关结构异常只适合线性
自编码器重构误差高维结构正常样本可压缩图像、文本等高维阈值难定,训练较娇气
CUSUM/滑动窗口时间序列序列平稳缓变与突发异常需要调窗口和阈值

6.2 按场景选型:一个可复用的决策流程

这么多方法,拿到实际项目时怎么选?我自己的决策流程大概是这样:先看数据类型,判断是表格数据、时序数据还是图像文本等非结构化数据。如果是单变量表格数据,先跑MAD或IQR做全量扫描;如果业务要求严格假设检验,再上Grubbs或GESD。如果是多变量数据且变量间有明显相关性,优先考虑马氏距离或PCA重构误差,同时用孤立森林跑一版作为对照。如果数据密度不均、存在明显簇结构,上LOF或DBSCAN。如果参数总量太大或者维度数百上千,隔离森林永远是性价比最高的那一档。时序数据则无脑先做滑动窗口观察,再用CUSUM补一个慢漂移检测通道。

选两个方法交叉验证也很重要。同一样本同时被两个不同派别的方法标记为异常,那它确实很可疑;只被一种方法检出,需要再多看可视化。

6.3 实测中绕不开的坑

这一路写下来,我发现一个规律:几乎所有方法失效,都逃不过下面几类问题。

masking与swamping。异常值污染了统计量,使得检测不到真异常,或者反过来把正常点误判成异常。规避办法就是优先用稳健统计量(中位数、MAD),并考虑GESD这类迭代消除方法。

分布误判。不检验数据分布就直接套正态公式,最常见错误。尤其收入、点击、时长这类数据,几乎都是长尾分布,直接3σ会把大量正常业务点标红。处理这类数据,先考虑取对数或Box-Cox变换,再用正态假设方法。

维度灾难。高维空间里距离趋向均匀,欧氏距离、马氏距离都是重灾区。这时候距离派方法会集体失效,换成基于树模型的孤立森林、基于重构误差的自编码器效果更好。特征能降维就降维,不是万不得已不要在高维空间硬算密度。

样本量太小。小于10个点时,任何基于分布估计的方法都不可靠。我建议小样本直接用视觉检查加业务规则,强上统计检验只有误导意义。

时序数据当独立样本处理。这是业务里最高频的错误:直接把序列上所有点混一起算均值和分位数。时序数据的每个点都和前后点相关,简单全局异常检测根本分不清趋势变化和真正的异常,必须优先考虑滑动窗口、CUSUM或者STL分解加残差检测。

重要提示:所谓"异常值检测"的最终结果只是候选名单,不是最终判断。所有统计方法都在给你提供关于"这个点有多不像大多数数据"的证据,至于它是不是业务层面必须处理的异常,要结合指标口径、采集链路和业务逻辑人工复核。要求100%自动定论、不审阅就删除异常记录,往往会把真实业务波动当成垃圾数据丢掉。

我个人在项目里的习惯是:每次检测都保留一份完整的异常清单,包含异常分数、命中的方法、样本上下文信息;交付给业务方时带上可视化图,让他们能一眼看到为什么标的这个点有问题。这套流程下来,模型上线后出幺蛾子的概率低了很多。数据清洗不是一次性的,把检测方法沉淀成周期性任务,配合业务反馈不断调整阈值,才是异常值管理的正确打开方式。

返回列表