数据预处理:异常值检测与处理方法归纳总结

好,到了第三章。前面我们聊了缺失值和数据类型,这一章我们专门对付那些「不合群」的数值——异常值。

异常值是什么?说白了就是那些明显偏离正常分布的样本。比如客户年龄填了200岁,或者月收入写了个-5000。这些数据如果不管,后面建模会出大问题。我早年做评分卡的时候,就因为漏掉了一批异常的收入数据,模型AUC直接掉了0.15。嗯,教训很深。

第一步:先搞清楚异常值从哪来

我习惯把异常值分成三类,这样后续处理才有针对性。

类型来源例子
人为录入错误手误、输入格式错位年龄写成了“230”
设备/系统异常传感器故障、网络传输丢包交易金额突然多两个零
真实但极端的业务现象大额存款、黑天鹅事件客户月收入100万(确实真实)
我的习惯:拿到数据后先画箱线图和直方图,肉眼扫一遍。别急着用算法,有时候异常值一眼就能看出来。

第二步:异常值检测的常用方法

方法很多,我这里只讲信用评分场景下最实用的几种。你不需要全用,选一个适合数据分布的就行。

1. Z-score(三西格玛法)

适用于近似正态分布的数据。计算每个样本与均值的距离,除以标准差。一般绝对值超过3就算异常。我在客户“负债率”变量上用过,效果不错。

import numpy as np
from scipy import stats

def detect_outliers_zscore(data, threshold=3):
    z = np.abs(stats.zscore(data))
    return np.where(z > threshold)[0]

2. IQR(四分位距法)

不依赖正态分布,用中位数和四分位数。定义下界 Q1 - 1.5*IQR,上界 Q3 + 1.5*IQR。超过边界就算异常。这是最通用的方法,我在几乎所有信用数据集上都会先用它扫一遍。

3. DBSCAN(基于密度的聚类)

把样本稠密区域归为簇,孤立的点标记为异常。适合分布不规则的数据,比如“客户消费金额”这种长尾分布。不过参数调起来比较麻烦,我建议先试试前两种。

4. 孤立森林(Isolation Forest)

随机切割特征空间,异常点更容易被孤立。速度快,适合高维数据。在“多头借贷”这种多变量场景下,我常用它做第一轮筛选。

避坑提醒:我曾经在“年龄”变量上直接用了Z-score,结果把60岁以上正常客户全部标成了异常。后来改用IQR,才保留住了这群高信用客户。所以一定要先观察分布。

第三步:异常值处理方法归纳

检测出来以后,怎么处理?下面这张表基本覆盖了所有常用策略。

方法适用场景注意
直接删除数据量大、异常比例低(低于5%)删除后要检查样本分布是否偏移
截尾(Winsorize)数值型特征、异常为极端值用边界值替换,保留样本数量
用中位数/均值填充异常值可视为缺失均值受异常影响大,优先用中位数
分箱(Binning)连续变量异常边界模糊将异常归入“最高档”或“最低档”
模型预测修正有足够正常样本做回归用正常值训练模型,预测替换异常

我个人最常用的组合是:先用IQR检测,然后对小比例异常直接删除,对大比例异常做截尾处理。比如征信查询次数这个变量,异常值往往集中在顶部,我给它设个99%分位值截断,既保留了样本量,又消除了极端影响。

一个实战技巧:如果某个特征的异常值占比超过10%,不要急着删。先看看这些“异常”样本在目标变量(是否违约)上的分布。有时候极端值恰恰是高风险的信号,应该保留并单独处理。

一张图看懂异常值检测与处理全流程

下面这张流程图是我在项目中整理的架构,涵盖了从原始数据到清洗后数据的完整链。你可以直接复制到自己的代码笔记里。

异常值检测与处理流程图 原始数据 异常值检测方法 Z-score IQR DBSCAN 孤立森林 异常值处理策略 直接删除 截尾替换 中位数填充 分箱处理 清洗后数据 💡 建议流程:原始数据 → IQR快速筛查 → 根据异常比例选择删除或截尾 → 检查业务合理性 → 清洗输出 (异常比例 < 5% 直接删除,5%~20% 截尾处理, > 20% 需重新审视特征定义)

第四步:动手前的检查清单

在实际代码跑起来之前,我建议你按下面这个顺序走一遍:

  1. 逐个特征看分布——箱线图、直方图,别只看统计量。
  2. 判断异常值是否为业务合理值——比如年收入500万在信用评分里可能不是异常,是优质客户。
  3. 选择检测方法——正态分布用Z-score,其他用IQR,多变量用孤立森林。
  4. 确定处理策略——先试删除,如果样本减少太多再换截尾。
  5. 回验效果——处理前后特征分布是否变好?目标变量关系是否保持?
一个小技巧:我习惯同时保留原始值和清洗后的值,建两套数据集。后续建模时对比一下,如果清洗后模型提升明显,说明异常值确实干扰了;如果没变化,可能异常值本来就无害,那就不用过度清洗。

好了,异常值这部分我们就聊到这。别看方法多,实际项目中你反复用的就那么两三个。关键是要理解数据背后的业务意义——别让算法帮你做完决定。下一环节我们会聊特征变换与标准化,把数值拉到同一个量级上。嗯,继续加油。