背景
3Sigma、Z-Score、box plot、Grubbs假设检验四种分布异常值检验方法可以帮助在数据中识别异常值,而在机器学习中,异常值的检测对模型性能和结果的准确性具有重要影响。
原理:通过计算数据的均值和标准差,然后确定在正态分布中距离均值3个标准差之外的数据点,将其视为异常值。
对机器学习的作用:可以在数据预处理阶段使用,帮助剔除明显偏离正常范围的数据点,提高模型的鲁棒性。
原理:类似于3 Sigma法,通过计算数据点与均值的偏差,以标准差为单位表示。超过阈值的数据点被认为是异常值。
对机器学习的作用:用于标准化数据,帮助模型更好地处理不同尺度的特征,同时检测和处理异常值。
原理:利用数据的四分位数范围和箱线图的上下边缘来识别异常值。数据点落在箱线图之外的被认为是异常值。
对机器学习的作用:可以用于可视化异常值的分布情况,帮助数据分析和清理。在模型训练前,可以基于箱线图的结果选择是否去除异常值。
原理:基于假设检验,Grubbs检验用于检测样本中是否存在显著的异常值,通过计算统计值和比较与临界值的关系。
对机器学习的作用:提供了一种统计学上的检验手段,可以更严格地判断数据中的异常值。在需要较高精度的应用中,可以考虑使用Grubbs检验来识别异常值。
在机器学习中,这些异常值检测方法有助于:
提高模型的鲁棒性,减少异常值对模型的负面影响。
改善数据质量,使得模型更加可靠。
在数据预处理阶段,更好地理解数据的分布特征,选择合适的数据清理策略。
在模型评估和解释结果时,排除异常值对评估结果的干扰,提高结果的可解释性。
代码实现
from ucimlrepo import fetch_ucirepo
# fetch dataset
wine = fetch_ucirepo(id=109)
# data (as pandas dataframes)
X = wine.data.features
y = wine.data.targets
# metadata
print(wine.metadata)
# variable information
print(wine.variables)
访问UCI机器学习数据集为实验进行数据支撑。这些数据是对意大利同一地区种植的葡萄酒进行化学分析的结果,但来自三个不同的品种。该分析确定了三种葡萄酒中每一种中发现的13种成分的数量。对其中连续型数据进行异常值检验。
Sigma法
import pandas as pd
# 定义函数 detect_outliers,接受两个参数:DataFrame 和需要检查的列名
def detect_outliers(df, column_names):
# 初始化一个空的 Index,用于存储异常值的索引
outlier_indices = pd.Index([])
# 遍历指定的列名列表
for column_name in column_names:
# 计算当前列的均值和标准差
mean = df[column_name].mean()
std = df[column_name].std()
# 计算异常值的阈值(标准差的3倍)
threshold = 3 * std
# 计算异常值的上下限(均值加减3倍标准差)
lower_limit = mean - threshold
upper_limit = mean + threshold
# 找出值在上下限之外的行
outliers = df[(df[column_name] < lower_limit) | (df[column_name] > upper_limit)]
# 将新找到的异常值索引与已有异常值索引合并
outlier_indices = outlier_indices.union(outliers.index)
# 返回所有异常值的索引列表
return outlier_indices
通过遍历给定的列名列表,在每列上计算均值和标准差,并基于标准差的3倍范围来识别异常值。异常值的索引最终被存储在一个包含所有异常值索引的索引对象中,并作为结果返回。
columns_to_check = X.columns
# 使用指定的列数据来运行 detect_outliers 函数,并返回异常值的索引列表
outlier_indices = detect_outliers(X, columns_to_check)
if not outlier_indices.empty:
print("超出三个标准差范围的索引:")
print(outlier_indices)
else:
print("没有数据超出三个标准差的范围")
图片
Z-score法
# 定义函数 detect_outliers,接受两个参数:DataFrame 和需要检查的列名
def detect_outliers(df, column_names):
# 初始化一个空的 Index,用于存储异常值的索引
outlier_indices = pd.Index([])
# 遍历指定的列名列表
for column_name in column_names:
# 计算当前列的均值和标准差
mean = df[column_name].mean()
std = df[column_name].std()
# 计算Z-score
z_scores = (df[column_name] - mean) / std
# 设置 Z-score 阈值,例如,选择阈值为 3,即超过3个标准差的值被认为是异常值
threshold = 3
# 找出Z-score绝对值大于阈值的行
outliers = df[abs(z_scores) > threshold]
# 将新找到的异常值索引与已有异常值索引合并
outlier_indices = outlier_indices.union(outliers.index)
# 返回所有异常值的索引列表
return outlier_indices
函数接受一个DataFrame和一个列名的列表作为输入,然后对每个指定的列进行Z-score异常值检测。对于每一列,它计算Z-score,然后通过设定的阈值(在这里是3)来判断哪些数据点是异常值。最终,函数返回所有异常值的索引列表。
columns_to_check = X.columns
# 使用指定的列数据来运行 detect_outliers 函数,并返回异常值的索引列表
outlier_indices = detect_outliers(X, columns_to_check)
if not outlier_indices.empty:
print("超出三个标准差范围的索引:")
print(outlier_indices)
else:
print("没有数据超出三个标准差的范围")
图片
Boxplot(箱线图)
import matplotlib.pyplot as plt
subset_data = X
plt.figure(figsize=(10, 6))
subset_data.boxplot()
plt.xticks(rotation=90)
plt.title('Boxplot')
plt.xlabel('Indicators')
plt.ylabel('Values')
plt.show()
图片
箱线图(Boxplot)是一种用于显示数据分布的图表类型,它提供了对数据中心位置、离散程度以及可能存在的异常值的直观理解。以下是关于如何解释箱线图的简单说明:
箱体(Box):箱体显示了数据分布的中间50%。箱体上边界表示数据的上四分位数(Q3),下边界表示下四分位数(Q1)。箱体的长度(上四分位数和下四分位数之间的距离)代表了数据的离散程度。
中位数线(Median Line):在箱体内部画一条线,表示数据的中位数,即数据的中间值。
须线(Whiskers):须线延伸自箱体,表示数据的范围。通常,须线会延伸到最大和最小非异常值的位置。但在某些情况下,须线可能会被截断,显示有可能是异常值的点。
异常值(Outliers):被认为是异常值的个别数据点通常被绘制为散点,位于须线之外。这些点可能表示数据中的极端值或测量错误。
如何阅读箱线图:
箱体的高度和长度:高度越大,说明数据的变异程度越大;长度越长,说明数据的离散程度越大。
中位数线的位置:中位数线在箱体中央,如果箱体偏向某一侧,表示数据可能存在偏斜。
须线的长度:须线的长度表征数据的范围。较长的须线表示数据更广泛,较短的表示数据较为集中。
异常值:散点表示的异常值可能需要进一步检查,以确定它们是否是真正的异常或者是错误值。
总体而言,箱线图是一种有效的工具,可以帮助了解数据的中心趋势、离散程度以及是否存在异常值。
Grubbs假设检验
import pandas as pd
import numpy as np
from scipy.stats import t
def detect_outliers_grubbs(df, column_names, alpha=0.05):
# 初始化一个空的 Index,用于存储异常值的索引
outlier_indices = pd.Index([])
# 遍历指定的列名列表
for column_name in column_names:
# 获取当前列的数据
data = df[column_name]
# 计算均值和标准差
mean = np.mean(data)
std = np.std(data, ddof=1) # 使用样本标准差,自由度为1
# 计算 Grubbs 检验的统计量
n = len(data)
t_critical = t.ppf(1 - alpha / (2 * n), n - 2)
g = (np.max(data) - mean) / std
# 设置 Grubbs 检验的阈值
threshold = ((n - 1) / np.sqrt(n)) * np.sqrt(t_critical**2 / (n - 2 + t_critical**2))
# 找出 Grubbs 检验的异常值
outliers = df[np.abs((data - mean) / std) > threshold]
# 将新找到的异常值索引与已有异常值索引合并
outlier_indices = outlier_indices.union(outliers.index)
# 返回所有异常值的索引列表
return outlier_indices
detect_outliers_grubbs 函数接受一个 DataFrame (df)、需要检查的列名列表 (column_names)以及显著性水平的可选参数 (alpha)。对于每个指定的列,该函数执行 Grubbs 检验,识别可能的异常值。对于每列,计算均值和样本标准差,并使用 Grubbs 检验的统计量计算可能的异常值。Grubbs 检验的阈值通过计算得到,如果数据中的值超过这个阈值,就被认为是异常值。找到的异常值的索引被存储在outlier_indices中,并最终返回。
columns_to_check = X.columns
# 使用指定的列数据来运行 detect_outliers_grubbs 函数,并返回异常值的索引列表
outlier_indices = detect_outliers_grubbs(X, columns_to_check)
if not outlier_indices.empty:
print("Grubbs 检验发现的异常值的索引:")
print(outlier_indices)
else:
print("没有通过 Grubbs 检验的异常值")
图片
注意,alpha 参数用于设置显著性水平,默认为 0.05。在 Grubbs 检验中,通常使用 t 分布的临界值来计算统计量。