type
Post
status
Published
summary
异常值可能是在数据采集、数据记录、数据提取等步骤中产生的,异常值的出现会对模型学习进行干扰,所以需要进行特殊处理。而在实际的生产环境中的异常值更是五花八门。
slug
date
Nov 2, 2023
tags
异常值
特征工程
数据预处理
箱型图
异常检测
category
机器学习
password
icon
URL
Property
Nov 6, 2023 03:19 AM
异常值是远离其他数据点的数据点。换句话说,它们是一个数据集中不同寻常的值。异常值对于许多统计分析是有问题的,因为它可能让我们错过显著发现或扭曲实际结果。

一、单变量异常检测

四分位距法(箱型图)

notion image
箱形图的上限和下限并不是数据集的最大值和最小值,而是经过一定的计算得到的,所以能检测到离群比较离谱的异常值
在 pandas 中,可以用 quantile 方法来计算指定的分位数,并结合箱型图的特性:1.5 倍四分位距离的特性来过滤异常值(可以适当调整倍数或分位数)
# 箱型图判断异常点 def box_outlier(data): df = data.copy(deep=True) out_index = [] for col in df.columns: # 对每一列分别用箱型图进行判断 Q1 = df[col].quantile(q=0.25) # 下四分位 Q3 = df[col].quantile(q=0.75) # 上四分位 low_whisker = Q1 - 1.5 * (Q3 - Q1) # 下边缘 up_whisker = Q3 + 1.5 * (Q3 - Q1) # 上边缘 # 寻找异常点,获得异常点索引值,删除索引值所在行数据 rule = (df[col] > up_whisker) | (df[col] < low_whisker) out = df[col].index[rule] out_index += out.tolist() df.drop(out_index, inplace=True) return df

标准差法(3σ 原则)

通常一组数据的标准差用 σ 表示,算术平均用 μ 表示。
对于服从正态分布的数据来说,约68.2%的数据在均值的一倍标准差之内。约有95.4%和99.7%的数据点在均值的两倍和三倍标准差以内。
3σ 原则是通过设置一个上限:μ + 3σ;一个下限:μ - 3σ;将分布在这个上下限范围之外的数据视为异常数据。
# 3sigma 原则 def treble_sigma_outlier(data): df = data.copy(deep=True) out_index = [] for col in df.columns: col_mean = df[col].mean() # 均值 col_std = df[col].std() # 标准差 low_whisker = col_mean - 3 * col_std # 下边缘 up_whisker = col_mean + 3 * col_std # 上边缘 # 寻找异常点,获得异常点索引值,删除索引值所在行数据 rule = (df[col] > up_whisker) | (df[col] < low_whisker) out = df[col].index[rule] out_index += out.tolist() df.drop(out_index, inplace=True) return df

z-score 法

Z分数是一种数学变换,它根据每个观测值与平均值的距离对其进行分类。该方法计算数组中每个值的z-score值,然后再根据设定的阈值来筛选样本,其计算公式为:
z-score 法其实与标准差法的底层逻辑一致,当设定的阈值为 [-3, 3] 时,其实就是 3σ 原则

二、多变量异常检测

聚类检测

使用聚类算法进行分簇,如果某一个簇里的样本数很少,而且簇质心和其他所有的簇都很远,那么这个簇里面的样本极有可能是异常特征样本了。
通常使用DBSCAN(密度)聚类方法进行异常值检测,它的优势是不用指定簇的数量。并且 DBSCAN 会直接给出噪点的标签(-1)。
import numpy as np from sklearn.cluster import DBSCAN from sklearn.preprocessing import MinMaxScaler glass_x = np.array(glass).astype('float') scaler = MinMaxScaler() glass_scaled = scaler.fit_transform(glass_x) # Initiate DBSCAN dbscan = DBSCAN(eps=0.4, min_samples=10) dbscan.fit(glass_scaled) glass['outlier'] = dbscan.labels_

孤立森林

孤立森林遵循随机森林的方法,但相比之下,它检测(或叫做隔离)异常数据点。它有两个基本假设:离群值是少数样本,且它们是分布偏离的。
孤立森林通过随机选择一个特征,然后随机选择一个分割规则来分割所选特征的值来创建决策树。这个过程一直持续到达到设置的超参数值。在构建好的孤立森林中,如果树更短且对应分支样本数更少,则相应的值是异常值(少数和不寻常)。
算法预测结果中,异常值背标记为 -1
from sklearn.ensemble import IsolationForest # Initiate isolation forest isolation = IsolationForest(n_estimators=100, contamination='auto', max_features=glass.shape[1]) # Fit and predict isolation.fit(glass) outliers_predicted = isolation.predict(glass) # Address outliers in a new column glass['outlier'] = outliers_predicted

局部异常因子 LOF

LOF是一种流行的无监督异常检测算法,它计算数据点相对于其邻居的局部密度偏差。计算完成后,密度较低的点被视为异常值。
算法预测结果中,异常值背标记为 -1
from sklearn.neighbors import LocalOutlierFactor glass_x = np.array(glass).astype('float') scaler = MinMaxScaler() glass_scaled = scaler.fit_transform(glass_x) clf = LocalOutlierFactor() outliers_predicted = clf.fit_predict(glass) glass['outlier'] = outliers_predicted

三、异常值处理

  • 直接删除
    • 如果异常数据量太大了,直接删除不仅会损失大量训练样本,并且会直接改变样本分布
    • 可以适当控制阈值的区间,来减少异常样本
  • 当成空值填充
    • 用一些统计值填充
  • 不做处理

推荐阅读:


  • Twikoo
  • Giscus
  • GitTalk
AnJhon
AnJhon
但知行好事,莫要问前程
公告
type
Notice
status
Published
summary
slug
date
Jul 21, 2023
tags
category
password
icon
URL
Property
Aug 4, 2023 04:45 AM
🚧🚧🚧
网站施工中~
🚧🚧🚧
📮你好,欢迎来到我的博客 🧑🏻‍💻我是Anjhon,一个学习者 📃这里记录了我的学习生活笔记 📬欢迎留言交流