机器学习中异常值的处理方式

2023-12-27 17:09:32

背景

3Sigma、Z-Score、box plot、Grubbs假设检验四种分布异常值检验方法可以帮助在数据中识别异常值,而在机器学习中,异常值的检测对模型性能和结果的准确性具有重要影响。

  • 3 Sigma法:

原理:通过计算数据的均值和标准差,然后确定在正态分布中距离均值3个标准差之外的数据点,将其视为异常值。

对机器学习的作用:可以在数据预处理阶段使用,帮助剔除明显偏离正常范围的数据点,提高模型的鲁棒性。

  • Z-score法:

原理:类似于3 Sigma法,通过计算数据点与均值的偏差,以标准差为单位表示。超过阈值的数据点被认为是异常值。

对机器学习的作用:用于标准化数据,帮助模型更好地处理不同尺度的特征,同时检测和处理异常值。

  • Boxplot(箱线图):

原理:利用数据的四分位数范围和箱线图的上下边缘来识别异常值。数据点落在箱线图之外的被认为是异常值。

对机器学习的作用:可以用于可视化异常值的分布情况,帮助数据分析和清理。在模型训练前,可以基于箱线图的结果选择是否去除异常值。

  • Grubbs假设检验:

原理:基于假设检验,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 分布的临界值来计算统计量。

civilpy:Python数据分析及可视化实例目录929 赞同 · 36 评论文章?编辑

文章来源:https://blog.csdn.net/baidu_22713341/article/details/135246136
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。