大数跨境

导师生气:“异常值一律删掉,模型就更准了?”我:“Codex帮我洗好了!”导师:“欺诈、故障、极端天气也删?你知道丢掉了什么吗?”

导师生气:“异常值一律删掉,模型就更准了?”我:“Codex帮我洗好了!”导师:“欺诈、故障、极端天气也删?你知道丢掉了什么吗?” 机器学习和人工智能AI
2026-11-06
4

哈喽,大家好~

今儿群里,有一个问题,“数据里有几个特别大的值,直接删掉可以吗?”

实施上是可以的,但你得先确认,它们到底是异常,还是业务中真实存在的极端情况。

在机器学习建模时,异常值经常会影响模型的学习方向。尤其是线性回归这类对数值比较敏感的模型,少量异常点就可能把整条回归线拉偏。

今天我们就用一个简单案例,看看如何识别异常值、删除异常值,并观察删除前后模型发生了什么变化~

01什么是异常值?

异常值,简单来说,就是和大多数样本明显不一样的数据。

比如,我们统计房屋面积和房价。大部分房子面积在   平方米之间,房价也基本随着面积增加而增加。但某一条数据可能是:

面积:80 平方米
房价:2000 万

它不一定是错误数据,也可能是学区房、豪宅或者录入错误。

所以,异常值处理不能只看“它是不是很大”,而要结合业务背景判断:

  • 如果是录入错误、传感器故障,可以删除或修正;
  • 如果是真实但极端的样本,不建议直接删除;
  • 如果异常样本很多,说明数据分布本身可能发生了变化。

就是说,删除异常值的前提,不是它看起来奇怪,而是它确实不代表我们想建模的正常规律。

02为什么异常值会影响线性回归?

线性回归希望找到一条直线,让预测值和真实值之间的误差尽可能小。

假设输入特征是  ,目标值是  ,线性回归公式为:

其中,  是斜率,表示   每增加一个单位,  大约变化多少;  是截距,表示   时的预测值。

模型通常通过最小化均方误差来训练:

这里的关键是平方。假设正常误差是  ,平方后是  ;但某个异常点误差是  ,平方后就变成了  。

也就是说,一个异常值产生的影响,可能相当于很多个正常样本。模型为了降低这个巨大的误差,就会主动把回归线往异常点方向拉。

03用 MAD 找出异常残差

我们先训练一个初始模型,然后计算每个样本的残差:

残差越大,说明真实值和模型预测值相差越远。

不过,直接使用均值和标准差容易再次受到异常值影响。因此这里使用 MAD,也就是中位数绝对偏差:

再计算稳健标准分数:

当   时,我们把它标记为候选异常值。

你可以这样理解:先用模型找到“偏离正常规律”的点,再把这些点从训练数据中移除,重新训练模型。

04完整案例

下面构造一组数据~

正常数据大致满足  ,同时人为加入几个明显偏离规律的异常点。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

np.random.seed(42)

# 构造正常数据
x = np.linspace(0, 10, 100)
y = 2.8 * x + 5 + np.random.normal(0, 1.5, 100)

# 加入异常值
outlier_index = [8, 25, 57, 78, 91]
y[outlier_index] += [18, -22, 25, -18, 20]

X = x.reshape(-1, 1)

# 第一次训练
model_before = LinearRegression()
model_before.fit(X, y)

y_pred = model_before.predict(X)
residual = y - y_pred

# 使用 MAD 计算稳健标准分数
median_residual = np.median(residual)
mad = np.median(np.abs(residual - median_residual))

robust_z = 0.6745 * (residual - median_residual) / mad
detected_outliers = np.abs(robust_z) > 3.5

# 删除异常值后重新训练
model_after = LinearRegression()
model_after.fit(X[~detected_outliers], y[~detected_outliers])
y_pred_after = model_after.predict(X)

print("识别出的异常值数量:", detected_outliers.sum())
print("删除前:斜率=%.2f,截距=%.2f" %
      (model_before.coef_[0], model_before.intercept_))
print("删除后:斜率=%.2f,截距=%.2f" %
      (model_after.coef_[0], model_after.intercept_))

# 绘图
plt.figure(figsize=(14, 5))

# 图1:删除前后回归线
plt.subplot(1, 2, 1)
plt.scatter(x[~detected_outliers], y[~detected_outliers],
            color="#00B4D8", s=45, label="正常样本")
plt.scatter(x[detected_outliers], y[detected_outliers],
            color="#FF4D6D", edgecolors="#6A0572",
            s=100, marker="X", label="异常样本")
plt.plot(x, y_pred, color="#FFB000", linewidth=3, label="删除前")
plt.plot(x, y_pred_after, color="#7B2CBF", linewidth=3, label="删除后")
plt.xlabel("特征 x")
plt.ylabel("目标值 y")
plt.title("异常值对回归线的影响")
plt.legend()
plt.grid(alpha=0.25)

# 图2:残差诊断
plt.subplot(1, 2, 2)
plt.scatter(y_pred, residual, color="#06D6A0", s=50)
plt.scatter(y_pred[detected_outliers], residual[detected_outliers],
            color="#FF4D6D", edgecolors="#6A0572",
            s=110, marker="X")
plt.axhline(0, color="#222222", linewidth=1.5)
plt.axhline(3.5 * mad / 0.6745, color="#FFB000",
            linestyle="--", linewidth=2)
plt.axhline(-3.5 * mad / 0.6745, color="#FFB000",
            linestyle="--", linewidth=2)
plt.xlabel("预测值")
plt.ylabel("残差")
plt.title("基于MAD的异常残差检测")
plt.grid(alpha=0.25)

plt.tight_layout()
plt.show()

第一张图中,蓝色点是正常样本,红色叉号是检测出的异常值~

黄色回归线表示删除异常值前的结果,紫色回归线表示删除后的结果。

如果异常值分布在回归线两侧,删除前后的变化可能不明显;但如果异常值集中在某一侧,删除前的回归线就会明显向异常点偏移。删除后,模型通常会更接近正常数据的真实趋势。

第二张图是残差诊断图。横轴是模型预测值,纵轴是残差。黄色虚线表示异常判断边界,落在边界外的点会被标记为异常。这个图能帮助我们判断:模型的误差是否随机分布,以及是否存在特别突出的样本。

05删除异常值时要注意什么?

第一,不要把异常值检测结果直接当成删除命令。模型识别出的只是“统计上的异常”,还需要结合业务规则确认。

第二,异常值检测要只使用训练集。不能先用完整数据删除异常值,再划分训练集和测试集,否则测试集信息会泄漏到训练过程中。

第三,删除异常值后要重新评估模型。重点观察验证集上的  、  或   是否真正改善,而不是只看训练集效果。

第四,如果异常值代表真实业务场景,比如欺诈交易、设备故障、极端天气,那么它们可能正是我们最关心的数据。这种情况下,与其删除,不如单独建模或增加异常样本特征。

总结

删除异常值的核心流程是:先训练初始模型,再通过残差识别明显偏离规律的样本,结合业务判断后删除,最后重新训练并评估模型。

在这个案例中,MAD比普通均值和标准差更不容易受到极端值影响,适合做稳健的异常检测。

后续大家还可以尝试使用 IsolationForest、LocalOutlierFactor 等方法处理多维异常值,也可以对比删除异常值、缩尾处理和使用 HuberRegressor 这类稳健模型之间的效果。

【声明】内容源于网络
0
0
机器学习和人工智能AI
让我们一起期待 AI 带给我们的每一场变革!推送最新行业内最新最前沿人工智能技术!
内容 446
粉丝 0
机器学习和人工智能AI 让我们一起期待 AI 带给我们的每一场变革!推送最新行业内最新最前沿人工智能技术!
总阅读10.0k
粉丝0
内容446