首页 > 编程问答 >数值数据中异常值检测的问题

数值数据中异常值检测的问题

时间:2024-08-08 05:17:15浏览次数:10  
标签:python machine-learning scikit-learn

我目前正在开展一个数据分析项目,在该项目中,我使用 Z 分数来检测数据集数值列中的异常值。但是,我遇到了一个问题,合法的数据点被标记为异常值,我不确定为什么会发生这种情况。

这就是我正在做的:

缺失值的插补:我使用 IterativeImputer sklearn.impute 填充数字列中的缺失值。 离群值检测:我计算每个数值列的 Z 分数,以使用阈值 3 检测离群值。 例如,我有一个埃及希腊罗马摔跤手 Yasser Abdel Rahman Sakr 的记录,其属性如下:

体重:120 公斤 身高: 180 厘米 尽管这些测量结果是合理的,但该记录被我的代码标记为异常值。其他记录也出现此问题。

以下是我的代码的相关部分:

    import numpy as np
    import pandas as pd
    from sklearn.impute import IterativeImputer

    # Assuming 'data' is already defined and loaded
    numeric_cols = data.select_dtypes(include=['float64', 'int64']).columns
    categorical_cols = data.select_dtypes(include=['object']).columns

    # Impute missing values in numeric columns
    mice_imputer = IterativeImputer(max_iter=10, random_state=0)
    df_numeric = pd.DataFrame(mice_imputer.fit_transform(data[numeric_cols]), columns=numeric_cols)

    # Combine imputed numeric columns with original categorical columns
    df_MICE = pd.concat([df_numeric, data[categorical_cols]], axis=1)

    # Dictionary to store outlier information
    outliers_info = {}

    for col in numeric_cols:
        # Calculate mean and standard deviation
        mean = df_MICE[col].mean()
        std_dev = df_MICE[col].std()
    
        # Avoid division by zero if std_dev is zero
        if std_dev == 0:
            print(f"Standard deviation is zero for column {col}. Skipping outlier detection.")
            continue
    
        # Calculate Z-scores
        z_scores = (df_MICE[col] - mean) / std_dev
    
        # Define outlier threshold
        threshold = 3
    
        # Find outliers
        outliers = df_MICE[np.abs(z_scores) > threshold]
    
        # Store the number of outliers and a sample of outliers in the dictionary
        outliers_info[col] = {
        'count': len(outliers),
        'sample': outliers.head(1)  # Sample of one outlier
        }

    # Print the number of outliers and a sample for each numerical column
    for col, info in outliers_info.items():
        print(f'Column: {col}')
        print(f'Number of outliers: {info["count"]}')
        if info['count'] > 0:
            print('Sample outlier:')
            print(info['sample'])
        else:
            print('No outliers.')
        print()  # Print a blank line for better readability

问题:

尽管是真实且合理的记录,但 Yasser Abdel Rahman Sakr 的体重和身高被标记为异常值。其他记录也会出现此问题。

问题:

什么可能导致合法数据点被标记为异常值? 在这种情况下是否有任何改进或替代方法可以更好地处理异常值检测? 我是否应该考虑其他因素或异常值检测方法? 感谢您提供的任何指导或建议。

谢谢!


发现的问题很常见:在使用 Z 分数等技术时,完全合法的数据点有时会被标记为异常值。以下是可能发生这种情况的原因,以及在的场景中可以考虑的改进和替代方案:

1. 异常值检测方法的局限性

  • Z 分数对异常值的敏感性: Z 分数高度依赖于均值和标准差,而均值和标准差很容易受到异常值的影响。当的数据集中存在极端值时,它会导致均值和标准差出现偏差,从而导致合法数据点被标记为异常值。
  • 数据分布的假设: Z 分数假设的数据呈正态分布。如果的数据不呈正态分布,则使用 Z 分数可能会导致异常值识别不准确。

2. 数据集的特定特征

  • 小数据集: 在较小的数据集中,单个异常值会对均值和标准差产生重大影响,从而使 Z 分数方法更容易出现错误。
  • 真实异常值的存在: 提到的 Yasser Abdel Rahman Sakr 的例子说明了这一点,即使在摔跤手等群体中,他的体重和身高也可能被认为是异常的。这凸显了上下文在异常值检测中的重要性。

改进和替代方案

  1. 稳健的异常值检测方法

  2. 四分位距 (IQR): IQR 是一种基于数据四分位数的稳健统计量度。它对异常值的影响较小。可以使用 IQR 方法通过将高于第三个四分位数 1.5 倍 IQR 或低于第一个四分位数 1.5 倍 IQR 的值标识为异常值来检测异常值。

  3. 中位数绝对偏差 (MAD): MAD 是数据点与其中位数之间绝对偏差的中位数。它对异常值具有很强的鲁棒性。

  4. 考虑数据分布

  5. 数据转换: 如果的数据不呈正态分布,请尝试使用对数转换或 Box-Cox 转换等技术对数据进行转换。这可以帮助使数据更接近正态分布,从而提高 Z 分数的可靠性。

  6. 非参数方法: 考虑使用非参数异常值检测方法,这些方法不假设数据呈特定分布。示例包括基于密度的局部异常值因子 (LOF) 和单类支持向量机 (OCSVM)。

  7. 上下文和领域知识

  8. 定义阈值: 不要盲目地依赖于诸如 3 之类的任意阈值,而是根据对数据的理解和问题的上下文来设置有意义的阈值。

  9. 审查标记的异常值: 始终手动审查标记为异常值的数据点,以确定它们是否确实是错误的,或者它们是否代表数据集中有趣的真实异常值。

的代码的改进

  • 实现 IQR 方法:
def find_outliers_iqr(df, col):
    """使用 IQR 方法查找给定 DataFrame 列中的异常值。
    """
    q1 = df[col].quantile(0.25)
    q3 = df[col].quantile(0.75)
    iqr = q3 - q1
    lower_bound = q1 - 1.5 * iqr
    upper_bound = q3 + 1.5 * iqr
    outliers = df[(df[col] < lower_bound) | (df[col] > upper_bound)]
    return outliers

# 针对每个数字列检测异常值
for col in numeric_cols:
    outliers = find_outliers_iqr(df_MICE, col)
    if len(outliers) > 0:
        outliers_info[col] = {
            'count': len(outliers),
            'sample': outliers.head(1)
        }
    else:
        outliers_info[col] = {
            'count': 0,
            'sample': None
        }
  • 探索数据转换和非参数方法,以便在 IQR 方法仍然产生太多误报时获得更准确的异常值检测。

请记住,没有一种放之四海而皆准的异常值检测方法。最有效的方法将取决于的特定数据集和问题的上下文。通过探索不同的方法、了解它们的优缺点,并结合领域知识,可以最大限度地提高准确识别真正异常值的可能性。

标签:python,machine-learning,scikit-learn
From: 78845677

相关文章

  • 为什么 Python NewType 与 isinstance 和 type 不兼容?
    这似乎不起作用:fromtypingimportNewTypeMyStr=NewType("MyStr",str)x=MyStr("HelloWorld")isinstance(x,MyStr)我什至没有得到False,但是TypeError:isinstance()arg2mustbeatypeortupleoftypes因为MyStr是一个函数......
  • Python & Selenium 4 & Edge 浏览器 |加载个人浏览器配置文件(包括cookie)
    使用Selenium4,我尝试加载我的个人浏览器配置文件(包括cookie),以便它可以加载到我之前登录过的网站。我正在使用边缘浏览器。在测试我的代码片段时,它似乎没有加载我的浏览器配置文件,而是创建一个新的(配置文件1)。我已确保配置文件的路径是正确的。我的代码片段:edge_opt......
  • 如何在通用 Python 类中输入 __eq__ ?
    当我定义带有泛型类型参数的类型时(例如K/V映射的键和值),我似乎无法编写合适的isinstance检查来实现__eq__:fromcollectionsimportOrderedDictfromcollections.abcimportMutableMappingfromtypingimportTypeVarK=TypeVar("K")......
  • 无法使用 devstack 安装 openstack 因为 python 版本
    我正在使用默认的python3.8.10运行./stack.sh,我收到此错误,因为我需要3.9或更高版本3.8msg错误但是当我将默认版本更改为3.9时,我收到错误没有找到模块“apt_pkg”3.9msgerror我一直在em之间来回跳动,但错误仍然存​​在(我也每次都会检查版本)......
  • Python @overload 使用联合类型会导致函数签名重叠错误
    我想编写以下重载的Python函数:fromtypingimportAny,TypeVar,overload_T1=TypeVar('_T1')_T2=TypeVar('_T2')_T3=TypeVar('_T3')@overloaddefparse_as(ty:type[_T1]|type[_T2],s:bytes)->_T1|_T2:...@overload......
  • python joblib.load 发生错误:协议 0 中的持久 ID 必须是 ASCII 字符串 在 GCP 云运行
    总体而言:我尝试使用Cloudbuild和Cloudrun构建BERT模型。我将模型(参数)和元数据(标签)保存在GCPCloudStorage中。但是,我遇到了通过joblib.load()加载metadata.bin文件的错误。我的metadata.bin文件包含UTF-8字符,但joblib.load需要ASCII字符。在......
  • Python + Svelte,如何使用本地文件系统
    总结一下,我有一个用python编写的应用程序。它在输入时需要一堆视频文件。使用一些魔法并生成合并的视频文件输出。我没有找到一个好的GUI解决方案(tkinter,QT,TUI等),所以我选择Svelte框架。但是出现了一个问题,我如何使用本地文件系统。在GUI(svelte)上,我必须上......
  • 如何在Python中绘制伪球面
    目标是使用meshgrid和numpy库生成伪球体的三维图形,但我使用下面的代码生成的图形不完整u=np.linspace(0,np.pi,50)v=np.linspace(0,2*np.pi,100)x,y=np.meshgrid(u,v)X=np.arccos(x)*np.cos(y)Y=np.arccos(x)*np.sin(y)Z=x-np.tan(x)fig=plt.f......
  • 18:Python集合属性
    #Python3集合#集合(set)是一个无序的不重复元素序列。#集合中的元素不会重复,并且可以进行交集、并集、差集等常见的集合操作。#集合中元素必须是不可变类型,也就说里面不能是列表和字典#可以使用大括号{}创建集合,元素之间用逗号,分隔,或者也可以使用set()函数创建集合。s......
  • Python爬虫案例与实战:爬取源代码练习评测结果
    Python爬虫案例与实战:爬取源代码练习评测结果本章案例将介绍用Python编写程序实现简单网站的模拟登录,然后保持登录后的网页会话,并在会话中模拟网页表单提交,之后使用Requests库的高级特性爬取提交之后的返回结果。在HTTP网页中,如登录、提交和上传等操作一般通过向网页发送......