在建模时,清理数据样本以确保观察结果能最好地代表问题非常重要。
有时数据集可能包含超出预期范围且与其他数据不同的极端值。这些被称为异常值,通过理解甚至移除这些异常值,通常可以改进机器学习建模和模型的整体技能。
在本教程中,您将了解异常值,以及如何从机器学习数据集中识别和移除它们。
完成本教程后,您将了解:
- 异常值是数据集中不太可能出现的观测值,可能由多种原因引起。
- 如何使用简单的单变量统计量(如标准差和四分位距)来识别和移除数据样本中的异常值。
- 如何使用异常值检测模型来识别和移除训练数据集中的行,以提升预测建模性能。
通过我的新书《机器学习数据准备》快速启动您的项目,书中包含分步教程和所有示例的Python 源代码文件。
让我们开始吧。
- 2018 年 5 月更新:修复了通过异常值限制过滤样本时的错误。
- 2020 年 5 月更新:更新以演示真实数据集。

如何使用统计数据识别数据中的异常值
摄影:Jeff Richardson,保留部分权利。
教程概述
本教程分为五个部分;它们是:
- 什么是异常值?
- 测试数据集
- 标准差法
- 四分位距法
- 自动异常值检测
什么是异常值?
异常值是与其他观测值不同的观测值。
它很少见,或者独特,或者某种程度上不符合。
我们通常将异常值定义为与数据主流异常偏远的样本。
——第 33 页,《应用预测建模》,2013 年。
异常值可能有很多原因,例如
- 测量或输入错误。
- 数据损坏。
- 真实的异常值观测(例如,篮球中的迈克尔·乔丹)。
通常没有精确的方法来定义和识别异常值,因为每个数据集都有其特殊性。相反,您或领域专家必须解释原始观测值并决定某个值是否为异常值。
即使对数据有透彻的理解,异常值也可能难以定义。[…] 应该非常小心,不要草率地删除或更改值,特别是当样本量很小时。
——第 33 页,《应用预测建模》,2013 年。
尽管如此,我们可以使用统计方法来识别在现有数据下显得稀有或不太可能发生的观测值。
识别数据集中的异常值和不良数据可能是数据清理中最困难的部分之一,并且需要时间才能做得正确。即使您对统计数据以及异常值如何影响数据有深入的了解,这始终是一个需要谨慎探索的话题。
——第 167 页,《使用 Python 进行数据整理》,2016 年。
这并不意味着识别出的值就是异常值,应该被移除。但是,本教程中描述的工具可以帮助揭示可能需要重新审视的罕见事件。
一个很好的建议是考虑绘制已识别的异常值,也许在非异常值的背景下,看看异常值是否存在任何系统关系或模式。如果有,也许它们不是异常值并且可以解释,或者异常值本身可以更系统地识别。
想开始学习数据准备吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
测试数据集
在研究异常值识别方法之前,我们先定义一个可以用于测试这些方法的数据集。
我们将生成一个包含 10,000 个从高斯分布中提取的随机数的总体,平均值为 50,标准差为 5。
从高斯分布中提取的数字将包含异常值。也就是说,由于分布本身的性质,会有一些值远离平均值,这些稀有值我们可以将其识别为异常值。
我们将使用 `randn()` 函数生成平均值为 0 且标准差为 1 的随机高斯值,然后将结果乘以我们自己的标准差并加上平均值,以将值移至首选范围。
伪随机数生成器被种子化,以确保每次运行代码时我们都能获得相同的数字样本。
1 2 3 4 5 6 7 8 9 10 11 |
# 生成高斯数据 from numpy.random import seed from numpy.random import randn from numpy import mean from numpy import std # 为随机数生成器设置种子 seed(1) # 生成单变量观测值 data = 5 * randn(10000) + 50 # 总结 print('mean=%.3f stdv=%.3f' % (mean(data), std(data))) |
运行示例将生成样本,然后打印平均值和标准差。正如预期的那样,这些值非常接近预期值。
1 |
平均值=50.049 标准差=4.994 |
标准差法
如果我们知道样本中值的分布是高斯分布或近似高斯分布,我们可以使用样本的标准差作为识别异常值的截止点。
高斯分布具有这样的特性:偏离平均值的标准差可以可靠地概括样本中值的百分比。
例如,在平均值的一个标准差内将覆盖 68% 的数据。
因此,如果平均值为 50,标准差为 5,如上述测试数据集所示,则样本中介于 45 到 55 之间的所有数据将占数据样本的约 68%。如果我们按如下方式扩展范围,可以覆盖更多数据样本:
- 偏离平均值 1 个标准差:68%
- 偏离平均值 2 个标准差:95%
- 偏离平均值 3 个标准差:99.7%
超出 3 个标准差的值属于分布的一部分,但它是一个不太可能发生的或罕见的事件,大约 370 个样本中出现 1 个。
在实践中,偏离平均值三个标准差是识别高斯或近似高斯分布中异常值的常用截止点。对于较小的数据样本,可以使用 2 个标准差(95%)的值;对于较大的样本,可以使用 4 个标准差(99.9%)的值。
给定均值(mu)和标准差(sigma),识别异常值的一种简单方法是为每个 xi 计算一个 z-分数,其定义为 xi 偏离均值的标准差数量 […] 具有超过阈值(例如 3)z-分数的 sigma 数据值被声明为异常值。
——第 19 页,《数据清洗》,2019 年。
我们通过一个实例来具体说明。
有时,数据会先进行标准化(例如,转换为零均值和单位方差的 Z-分数),以便可以使用标准 Z-分数截止值执行异常值检测。这是一种便利,但并非一般必需,我们将在原始数据尺度上执行计算,以使事情清晰。
我们可以计算给定样本的均值和标准差,然后计算偏离均值超过 3 个标准差的异常值识别截止点。
1 2 3 4 5 6 |
... # 计算汇总统计量 data_mean, data_std = mean(data), std(data) # 识别异常值 cut_off = data_std * 3 lower, upper = data_mean - cut_off, data_mean + cut_off |
然后我们可以将超出定义的下限和上限的例子识别为异常值。
1 2 3 |
... # 识别异常值 outliers = [x for x in data if x < lower or x > upper] |
或者,我们可以从样本中过滤掉那些不在定义限制内的值。
1 2 3 |
... # 移除异常值 outliers_removed = [x for x in data if x > lower and x < upper] |
我们可以将所有这些与上一节准备的样本数据集结合起来。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# 使用标准差识别异常值 from numpy.random import seed from numpy.random import randn from numpy import mean from numpy import std # 为随机数生成器设置种子 seed(1) # 生成单变量观测值 data = 5 * randn(10000) + 50 # 计算汇总统计量 data_mean, data_std = mean(data), std(data) # 识别异常值 cut_off = data_std * 3 lower, upper = data_mean - cut_off, data_mean + cut_off # 识别异常值 outliers = [x for x in data if x < lower or x > upper] print('Identified outliers: %d' % len(outliers)) # 移除异常值 outliers_removed = [x for x in data if x >= lower and x <= upper] print('Non-outlier observations: %d' % len(outliers_removed)) |
运行该示例将首先打印已识别的异常值数量,然后打印非异常值观测值的数量,分别演示了如何识别和过滤异常值。
1 2 |
识别出的异常值:29 非异常值观测:9971 |
到目前为止,我们只讨论了具有高斯分布的单变量数据,例如单个变量。如果您有多变量数据,例如具有多个变量且每个变量具有不同高斯分布的数据,您也可以使用相同的方法。
您可以想象,如果只有两个变量,二维中的边界将定义一个椭圆。落在此椭圆之外的观测值将被视为异常值。在三维中,这将是一个椭球,以此类推到更高维度。
或者,如果您对领域有更多了解,也许可以通过超出数据维度的一个或子集的限制来识别异常值。
四分位距法
并非所有数据都是正态的,或者足够正态以将其视为来自高斯分布的数据。
总结非高斯分布数据样本的一个很好的统计量是四分位距,简称 IQR。
IQR 是通过计算数据 75 百分位和 25 百分位之间的差值得出的,它定义了箱线图中的“箱体”。
请记住,可以通过对观测值进行排序并选择特定索引处的值来计算百分位数。第 50 百分位数是中间值,或者对于偶数个示例而言是两个中间值的平均值。如果我们的样本为 10,000 个,那么第 50 百分位数将是第 5000 个和第 5001 个值的平均值。
我们将百分位数称为四分位数(“quart”表示 4),因为数据通过第 25、50 和 75 个值被分成四个组。
IQR 定义了数据的中间 50%,或者说是数据的主体。
基于统计的异常值检测技术假设正常数据点将出现在随机模型的高概率区域,而异常值将出现在随机模型的低概率区域。
——第 12 页,《数据清洗》,2019 年。
IQR 可以通过定义样本值的限制来识别异常值,这些限制是 IQR 的一个因子 k 低于第 25 百分位数或高于第 75 百分位数。因子 k 的常用值为 1.5。当在箱线图的上下文中描述时,可以使用 3 或更大的因子 k 来识别极端异常值或“远端值”。
在箱线图上,这些限制被绘制为从箱体引出的“须”(或线条)上的“围栏”。超出这些值的数据点以点状绘制。
我们可以使用 `percentile()` NumPy 函数计算数据集的百分位数,该函数接受数据集和所需百分位数的规格。然后,IQR 可以计算为第 75 百分位数和第 25 百分位数之间的差值。
1 2 3 4 |
... # 计算四分位距 q25, q75 = percentile(data, 25), percentile(data, 75) iqr = q75 - q25 |
然后我们可以将异常值截止点计算为 IQR 的 1.5 倍,并从第 25 百分位数中减去此截止点,再将其加到第 75 百分位数中,以给出数据的实际限制。
1 2 3 4 |
... # 计算异常值截止点 cut_off = iqr * 1.5 lower, upper = q25 - cut_off, q75 + cut_off |
然后我们可以使用这些限制来识别异常值。
1 2 3 |
... # 识别异常值 outliers = [x for x in data if x < lower or x > upper] |
我们还可以使用这些限制从数据集中过滤掉异常值。
1 2 3 |
... # 移除异常值 outliers_removed = [x for x in data if x > lower and x < upper] |
我们可以将所有这些结合起来,并在测试数据集上演示该过程。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# 使用四分位距识别异常值 from numpy.random import seed from numpy.random import randn from numpy import percentile # 为随机数生成器设置种子 seed(1) # 生成单变量观测值 data = 5 * randn(10000) + 50 # 计算四分位距 q25, q75 = percentile(data, 25), percentile(data, 75) iqr = q75 - q25 print('Percentiles: 25th=%.3f, 75th=%.3f, IQR=%.3f' % (q25, q75, iqr)) # 计算异常值截止点 cut_off = iqr * 1.5 lower, upper = q25 - cut_off, q75 + cut_off # 识别异常值 outliers = [x for x in data if x < lower or x > upper] print('Identified outliers: %d' % len(outliers)) # 移除异常值 outliers_removed = [x for x in data if x >= lower and x <= upper] print('Non-outlier observations: %d' % len(outliers_removed)) |
运行该示例首先打印识别出的第 25 百分位数和第 75 百分位数以及计算出的 IQR。然后打印识别出的异常值数量,接着打印非异常值观测值的数量。
1 2 3 |
百分位数:第 25 = 46.685,第 75 = 53.359,IQR = 6.674 识别出的异常值:81 非异常值观测:9919 |
通过依次计算数据集中每个变量的限制,并将落在矩形或超矩形之外的观测值视为异常值,该方法可用于多变量数据。
自动异常值检测
在机器学习中,解决异常值检测问题的一种方法是单类分类。
单类分类,简称 OCC,涉及在“正常”数据上拟合模型,并预测新数据是正常还是异常/异常情况。
单类分类器旨在捕捉训练实例的特征,以便能够区分它们和可能出现的潜在异常值。
——第 139 页,《从不平衡数据集中学习》,2018 年。
单类分类器在一个只包含正常类别样本的训练数据集上进行拟合。一旦准备好,该模型用于将新样本分类为正常或非正常,即异常值或异常。
识别异常值的一个简单方法是找到那些在特征空间中与其他示例相距甚远的示例。
这对于低维度的特征空间(少数特征)可能效果很好,但随着特征数量的增加,其可靠性会降低,这被称为维度诅咒。
局部异常因子(LOF)是一种尝试利用最近邻思想进行异常值检测的技术。每个示例都被分配一个评分,表明其孤立程度或基于其局部邻域大小而成为异常值的可能性。得分最高的示例更有可能是异常值。
我们为数据集中的每个对象引入一个局部异常值 (LOF),以表明其异常程度。
——LOF:识别基于密度的局部异常值,2000 年。
scikit-learn 库在 LocalOutlierFactor 类中提供了这种方法的实现。
我们可以在一个预测建模数据集上演示 LocalOutlierFactor 方法。
我们将使用波士顿房价回归问题,该问题有 13 个输入和一个数值目标,需要学习郊区特征与房价之间的关系。
数据集可在此处下载
查看数据集,您应该会发现所有变量都是数值型。
1 2 3 4 5 6 |
0.00632,18.00,2.310,0,0.5380,6.5750,65.20,4.0900,1,296.0,15.30,396.90,4.98,24.00 0.02731,0.00,7.070,0,0.4690,6.4210,78.90,4.9671,2,242.0,17.80,396.90,9.14,21.60 0.02729,0.00,7.070,0,0.4690,7.1850,61.10,4.9671,2,242.0,17.80,392.83,4.03,34.70 0.03237,0.00,2.180,0,0.4580,6.9980,45.80,6.0622,3,222.0,18.70,394.63,2.94,33.40 0.06905,0.00,2.180,0,0.4580,7.1470,54.20,6.0622,3,222.0,18.70,396.90,5.33,36.20 ... |
无需下载数据集,我们将自动下载。
首先,我们可以将数据集加载为 NumPy 数组,将其分为输入变量和输出变量,然后将其拆分为训练和测试数据集。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 加载并汇总数据集 from pandas import read_csv from sklearn.model_selection import train_test_split # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv' df = read_csv(url, header=None) # 检索数组 data = df.values # 分割输入和输出元素 X, y = data[:, :-1], data[:, -1] # 总结数据集的形状 print(X.shape, y.shape) # 拆分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # 总结训练集和测试集的形状 print(X_train.shape, X_test.shape, y_train.shape, y_test.shape) |
运行该示例会加载数据集,首先报告数据集中的总行数和列数,然后报告分配给训练集和测试集的示例数量。
1 2 |
(506, 13) (506,) (339, 13) (167, 13) (339,) (167,) |
这是一个回归预测建模问题,这意味着我们将预测一个数值。所有输入变量也都是数值型的。
在这种情况下,我们将拟合一个线性回归算法,并通过在测试数据集上训练模型并在测试数据上进行预测,然后使用平均绝对误差(MAE)评估预测来评估模型性能。
下面列出了在数据集上评估线性回归模型的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# 在原始数据集上评估模型 from pandas import read_csv from sklearn.model_selection import train_test_split 来自 sklearn.linear_model 导入 LinearRegression from sklearn.metrics import mean_absolute_error # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv' df = read_csv(url, header=None) # 检索数组 data = df.values # 分割输入和输出元素 X, y = data[:, :-1], data[:, -1] # 拆分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # 拟合模型 模型 = LinearRegression() model.fit(X_train, y_train) # 评估模型 yhat = model.predict(X_test) # 评估预测 mae = mean_absolute_error(y_test, yhat) print('MAE: %.3f' % mae) |
运行该示例将拟合并评估模型,然后报告 MAE。
注意:您的结果可能会因算法或评估程序的随机性,或数值精度的差异而有所不同。考虑运行几次示例并比较平均结果。
在这种情况下,我们可以看到模型实现了大约 3.417 的 MAE。
1 |
平均绝对误差 (MAE): 3.417 |
接下来,我们可以尝试从训练数据集中移除异常值。
期望是异常值导致线性回归模型学习到对问题的偏差或倾斜理解,并且从训练集中移除这些异常值将允许学习到更有效的模型。
我们可以通过定义 LocalOutlierFactor 模型并用它对训练数据集进行预测来实现这一点,将训练数据集中的每一行标记为正常 (1) 或异常 (-1)。我们将使用异常值检测模型的默认超参数,但最好根据数据集的具体情况调整配置。
1 2 3 4 |
... # 识别训练数据集中的异常值 lof = LocalOutlierFactor() yhat = lof.fit_predict(X_train) |
然后我们可以使用这些预测来从训练数据集中移除所有异常值。
1 2 3 4 |
... # 选择所有非异常值的行 mask = yhat != -1 X_train, y_train = X_train[mask, :], y_train[mask] |
然后我们可以像往常一样拟合和评估模型。
下面列出了从训练数据集中删除异常值后评估线性回归模型的更新示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# 在移除异常值的训练数据集上评估模型 from pandas import read_csv from sklearn.model_selection import train_test_split 来自 sklearn.linear_model 导入 LinearRegression from sklearn.neighbors import LocalOutlierFactor from sklearn.metrics import mean_absolute_error # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv' df = read_csv(url, header=None) # 检索数组 data = df.values # 分割输入和输出元素 X, y = data[:, :-1], data[:, -1] # 拆分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # 总结训练数据集的形状 print(X_train.shape, y_train.shape) # 识别训练数据集中的异常值 lof = LocalOutlierFactor() yhat = lof.fit_predict(X_train) # 选择所有非异常值的行 mask = yhat != -1 X_train, y_train = X_train[mask, :], y_train[mask] # 总结更新后的训练数据集的形状 print(X_train.shape, y_train.shape) # 拟合模型 模型 = LinearRegression() model.fit(X_train, y_train) # 评估模型 yhat = model.predict(X_test) # 评估预测 mae = mean_absolute_error(y_test, yhat) print('MAE: %.3f' % mae) |
运行该示例将拟合并评估从训练数据集中删除异常值后的线性回归模型。
注意:您的结果可能会因算法或评估程序的随机性,或数值精度的差异而有所不同。考虑运行几次示例并比较平均结果。
首先,我们可以看到训练数据集中的示例数量已从 339 减少到 305,这意味着识别并删除了 34 行包含异常值的行。
我们还可以看到 MAE 有所下降,从拟合整个训练数据集的模型得到的约 3.417,下降到拟合移除异常值的数据集模型得到的约 3.356。
1 2 3 |
(339, 13) (339,) (305, 13) (305,) MAE: 3.356 |
Scikit-Learn 库提供了其他异常值检测算法,可以使用相同的方式,例如 IsolationForest 算法。有关自动异常值检测的更多示例,请参阅教程
扩展
本节列出了一些您可能希望探索的扩展本教程的想法。
- 开发您自己的高斯测试数据集,并在直方图上绘制异常值和非异常值。
- 在非高斯分布生成的单变量数据集上测试基于 IQR 的方法。
- 选择一种方法,并创建一个函数,用于过滤具有任意维度的数据集中的异常值。
如果您探索了这些扩展中的任何一个,我很想知道。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
教程
书籍
- 应用预测建模, 2013.
- 数据清洗, 2019.
- 使用 Python 进行数据整理, 2016.
API
文章
总结
在本教程中,您了解了异常值,以及如何从机器学习数据集中识别和移除它们。
具体来说,你学到了:
- 异常值是数据集中不太可能出现的观测值,可能由多种原因引起。
- 如何使用简单的单变量统计量(如标准差和四分位距)来识别和移除数据样本中的异常值。
- 如何使用异常值检测模型来识别和移除训练数据集中的行,以提升预测建模性能。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
解释得很清楚。做得很好。
谢谢。
你好,你能用 R 解释一下,如何使用 Q1-1.5*IQR 和 Q3+1.5*IQR 找出单个变量中有多少异常值吗?请只用 R 帮助我,因为我是分析新手。
抱歉,我没有这方面的 R 语言示例。
你好,杰森,我正考虑购买你在文章末尾提到的关于机器学习数据准备的书。
我想问一下这篇关于异常值的教程是否在书中包含更多细节。
您的书通常会更详细地包含所有博客文章吗?
谢谢
这本书确实包含了本教程的一个版本。
有关书籍和文章之间区别的更多信息,请参阅此处
https://machinelearning.org.cn/faq/single-faq/how-are-your-books-different-from-the-blog
使用 summary(variable) 方法
非常有帮助。谢谢。
很高兴听到这个消息。
一旦我移除了异常值,如何填补异常值留下的空间?因为在其他特征中,长度比移除异常值后的特征要多。
整个记录可以被移除。
或者,可以移除记录中的值,然后进行插补。
https://machinelearning.org.cn/handle-missing-data-python/
Jason Brownlee 的文章和内容一如既往地精彩。
谢谢!
如果假设我们有 50 个特征,并且我们对每个特征都运行此操作,那么由于数据缺失,我要删除的行数会不会很多?
另外,dbscan 会比这更可取吗?
可能吧。这是一种非常简单/粗略的方法,可能不适用于大量特征。
或者,可以删除观测值,然后填补缺失值。
我喜欢你的帖子,我觉得用绘图会更好。
感谢您的建议。
您的代码有缺陷——特别是分位数示例,它基于数据集中的数据点定义异常值边界。如果您的异常值 > < 边界,而您的非异常值是 ,那么您的边界会从这两个集合中缺失。
你到底是什么意思,能举个具体的例子吗?
我假设 Yishai 的意思是我们需要在代码中添加一个 '>=` 和 '<=' 来包含等于上限/下限的样本。
嗨,杰森博士。
感谢您提供的所有技巧,我长期以来一直在关注您的帖子。
我不知道,这里是否是提出我以下问题的正确论坛。我正在尝试评估各种分类算法,如决策树、ADtree 等,用于检测候选人是否患有自闭症的特定问题,使用众所周知的访谈问卷 ADI-R。各种文献声称使用 A 算法或 B 算法来展示他们如何减少问题集(最初 99 个问题),同时仍然获得很高的准确性。许多文献指出 Adtree 最适合此目的。然而,Adtree 有其自身的局限性。我很困惑。您能否解释一下,考虑到这个问题的复杂性,最好的方法是什么。
问题究竟是什么?
我一直在思考标准差方法,以及一些人提出一个非常大的异常值可能会使均值和标准差产生足够的偏差,从而干扰异常值移除。
然而,这个问题是否可以通过将每个值与来自所有其他值(不包括当前列表中正在查看的那个值)的均值和标准差所产生的边界进行比较来缓解?如果当前正在查看的那个值是一个异常值,那么它将被排除在均值和标准差计算之外,使其更有可能被视为异常值,即使它是一个非常大的值。
这种方法在效率方面可能存在成本,但根据应用情况,这种成本可能值得。谢谢!
在计算限制之前,通过目视检查数据图表以确保它们合理可能更容易。
感谢你的帖子,杰森。它启发我编写了一个 Kaggle 内核,更详细地探讨了这个主题。我实现了你的标准差和 IQR 方法 🙂
https://www.kaggle.com/kevinarvai/outlier-detection-practice-uni-multivariate
干得好!凯文,那是一个非常出色的内核。
嗨,杰森,这些方法是否包含在你的新书《机器学习统计方法》中?
它们是我认为你在进行应用机器学习项目时需要知道如何使用的方法。
尊敬的先生,
我使用 IQR 方法在 python 中绘制箱线图时遇到问题,我知道中位数、最小值、最大值、Q1、Q3。您能帮我一下吗?
也许 API 会有所帮助
https://matplotlib.net.cn/api/_as_gen/matplotlib.pyplot.boxplot.html
尊敬的先生,
我没听懂。您能详细解释一下吗?
嗨,Jason,
我的数据标准差非常接近均值。所以当我执行
lower = mean – cutoff
它会给我一个负数。这没关系吗?我的数据不包含小于 0 的值。
也许这种方法不适合你的数据?
嗨,Jason,
当您说数据需要首先标准化时,您是指数据转换(归一化、标准缩放器、Box-cox)吗?
明确地讲是标准化,零均值和单位标准差。
嗨,Jason,
感谢您的专业知识!
使用您的 IRM 代码时,我遇到以下 TypeError
TypeError Traceback (most recent call last)
in ()
9 lower, upper = q25 – cutoff, q75 + cutoff
10 # 识别异常值
—> 11 outliers = [x for x in dfg if x upper]
12 print('识别出的异常值: %d' % len(outliers))
13 # 移除异常值
在 (.0)
9 lower, upper = q25 – cutoff, q75 + cutoff
10 # 识别异常值
—> 11 outliers = [x for x in dfg if x upper]
12 print('识别出的异常值: %d' % len(outliers))
13 # 移除异常值
TypeError: ' > ' 不支持 'numpy.ndarray' 和 'str' 实例之间
很抱歉听到这个消息,我有一些建议给你
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
您能发一篇关于使用 Python 将异常值替换为中位数的帖子吗?
谢谢
感谢您的建议。
非常感谢,很有帮助。
很高兴听到这个消息。
嗨,Jason,
感谢这篇精彩的文章。我已将其应用于我的数据集。但在进行 train_test split 时,我收到以下错误
ValueError: 发现输入变量的样本数量不一致:[459, 489]。
请建议如何解决形状不一致的问题
很抱歉听到这个消息,我有一些建议给你
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
嗨,Jason,
感谢你所做的出色工作。我刚刚开始研究机器学习,以解决我们遇到的一些问题。
最近我一直在尝试使用机器学习来检测机器(如电机)的问题,基于从它们收集的振动数据。这将是时间序列数据。当机器开始磨损时,振动数据开始飙升。所以理想情况下,数据会是完全健康的,并且随着机器运行一段时间,振动数据会慢慢开始变化。机器学习算法应该在这些偏差发生时发现它们。您会推荐哪种方法来解决这种场景?统计方法、ARIMA、神经网络……提前感谢。
我建议研究“变化检测”算法。
非常清晰的异常值介绍和实用代码。谢谢~
谢谢,很高兴对您有帮助。
你好,
您将如何证明使用四分位距方法优于其他方法来识别异常值?也就是说,它有什么特别的优点,在什么情况下我们会优先使用它而不是其他方法?
谢谢
它简单易懂。
其他方法可能复杂且难以理解。
你好,
请问如何选择 Z 分数或 IQR 方法来从数据集中移除异常值。
数据集是 Likert 5 量表数据,包含大约 30 个特征和 800 个样本,我正在尝试将数据聚类成组。
如果我计算 Z 分数,大约 30 行出现异常值,而 IQR 方法会识别出 60 行异常值。
我很困惑应该选择哪一个。
谢谢。
也许可以尝试一系列值,评估它们对数据的影响,然后选择一个能产生预期效果的值。
你可能想绘制结果,例如异常值与非异常值。
你好,
如果我只有 6 个数据点,使用这种方法有用吗?
或者我需要的最少点数是多少?
谢谢!
可能不会。至少 30 点。
解释得很清楚!
在这种情况下,我们已经移除了异常值
假设我们想用 NAN 替换异常值,如何做到这一点
你能解释一下吗
提前感谢
你可以获取异常值值的索引,并将这些索引处的值设置为任何你希望的值,例如 NaN。
您也可以使用 replace() 函数,我在这里给出一个示例
https://machinelearning.org.cn/handle-missing-data-python/
你好 Jason,
据我理解,使用
“outliers = [x for x in data if x upper]”
我们得到一个异常值列表(而不是索引)。
假设我们有一个多变量 DataFrame,我们如何获取异常值的位置?
意思是:我们能否获取一个包含异常值索引的列表,以便我们直接删除它们?
非常感谢您有趣的这篇文章!
Artur
也许使用 where() numpy 函数?
谢谢杰森,
我也是这么想的,但到目前为止,np.where() 函数只给我第一个感兴趣列中异常值的位置。也许我的循环有问题。
但我找到了另一种方法 🙂
很高兴听到这个消息。
您是否有关于您这一说法的参考文献:“总结非高斯分布数据样本的一个好统计量是四分位距,简称 IQR。” 就个人而言,我不能确定 IQR 适用于所有非高斯分布,但如果您能提供参考文献,我很乐意了解更多。
无论如何,感谢您撰写了这些优秀的文章。
这是一种启发式方法,而非规则,例如并非所有情况都适用。
任何一本好的统计学书籍都会描述这种方法。
另请参阅此
https://en.wikipedia.org/wiki/Interquartile_range#Outliers
如何发现多元数据中的异常值,因为每个特征都有自己的值。
也许从每个特征的单变量方法开始?
嗨,杰森,感谢您的快速回复。我能够按照上述说明提取单变量数据中的异常值,但是如何在多变量数据中应用此过程呢?有没有办法通过考虑模式中的所有实例来检测多变量数据中的异常值?
您可能需要在用尽单变量方法后,查阅关于多变量方法的文献。
箱线图或直方图是否可以应用于在整个数据集(即数据集中所有数据列)上查找异常值,还是我们必须在每个单独的列上应用它?
是的,但它是一次应用于一列。
谢谢!
有没有办法,不是移除异常值,而是用某些值替换它们,这样我们的数据集的形状就不会改变?
也许吧,但为什么要这样做?
因为如果我们移除异常值,那么数据集中所有列的数据数量将不同,这可能会给模型训练带来困难。
测试并确认。
嗨,Jason,
这篇文章非常有帮助。谢谢。
我有一个疑问。在考虑 IQR 逻辑时,我们如何确定常数的值?为什么通常将其视为 1.5?
另外,我们能否在此常数和 IQR 值之间定义某种关系,以便获得数据依赖的常数值?
谢谢。
根据标准定义,该常数为 1.5。无需更改——它已经是数据独立的。
我们能用 django/正则表达式/直方图检测异常值吗?或者用以上三种函数都行?
或许可以测试一下看看?
嗨,Jason,
为什么异常值只从训练数据集中移除?而不从测试数据集中移除?
在预测过程中,模型会遇到测试数据集中的异常值吗?
请给出您的建议。谢谢。
如果您从测试数据中移除异常值,则不会对它们进行任何预测。
这可能合乎期望,也可能不合乎期望,具体取决于您的项目目标。
你好,
这篇艺术性文章很棒。杰森总是解释得很好。
谢谢!
嗨,Jason,
我很欣赏这是一篇“操作指南”文章,但我觉得你对移除异常值可能带来的问题有些轻描淡写了,如果能提供更多细节会很有用。
移除异常值可能是一种让数据看起来整洁的好方法,但应该强调的是,在许多情况下,您正在从数据集中移除有用的信息。在小型(n<100)数据集中尤其如此。与其丢弃它们并继续进行有趣的部分,我将异常值视为我需要深入研究数据并更好地理解问题空间的提示。
谢谢您的留言。
像其他转换一样,测试并确认它能提升您的建模流程在测试工具上的性能。
既然我们已经从训练数据中移除了异常值,为什么我们不也检测并移除测试数据中的异常值,以获得更好的结果呢?
你可以这样做,如果你认为这是评估模型的一种有效方式。例如,系统可能会报告“无法预测”或类似信息。
嗨,Jason,一如既往的棒!!!🙂
我对标准差测试有疑问,它通常应用于正态分布。
但是,将偏斜数据正态化,然后使用相同的方法查找异常值,这是一种正确的方法吗?
是的,你可以先将数据正态化,然后使用该方法。
那么什么时候使用四分位距法呢?
当数据分布不是高斯分布时。
好的,那么,对于偏斜数据,我们通常应该使用哪种方法?IQR还是标准差方法?
还是选择真的取决于手头的问题?
这总是取决于情况。
一种方法是使用幂变换再使用高斯方法。另一种方法是直接使用IQR方法。
使用能产生最佳预测建模结果的方法。
解释得很清楚!
谢谢!
你的博客是机器学习新手必读的,非常感谢。
谢谢!
亲爱的Brownlee,这个演示似乎是基于序列或numpy数组(基本上是单列)的数据集,这样很好,你可以删除单列的异常值。
当我们有一个pandas数据框,并且每一列有不同数量的异常值时,如何处理异常值的删除呢?在这种情况下,我们对单列(例如)删除异常值,这将影响行级别的整个记录。这意味着如果我们考虑所有列的异常值并删除每列的异常值,最终数据集中只剩下很少的记录。这意味着删除一列的异常值会影响其他列。
我想说的是,异常值是在列级别检测到的,但删除是在行级别进行的,这会破坏数据集。
你仍然认为在机器学习中删除异常值是实用的吗?你对此有什么看法?
此致,
Satish
您可以将相同的方法应用于每个变量。
或者,您可以尝试更复杂的方法。
https://machinelearning.org.cn/model-based-outlier-detection-and-removal-in-python/
移除异常值是否有效取决于数据集和所使用的模型。也许可以尝试一下,并将结果与使用原始数据集进行比较。
嗨,杰森,我已经运行了你的代码,但是用我的数据框
问题是如何将机器学习结果导出为数据框格式到Excel?
您可以将结果保存为CSV,以便稍后在excel中加载,这将在python中向您展示如何操作。
https://machinelearning.org.cn/how-to-save-a-numpy-array-to-file-for-machine-learning/
首先,谢谢您的回复,先生。但是我想说的是,当我尝试打印(y_test, yhat)时,输出结果是一个数组,但是初始输入是数据框。我的问题是如何生成一个带有期望的异常值(没有输出)的数据框?
您可以直接从数组创建数据框。
也许这会有帮助。
https://pandas.ac.cn/pandas-docs/stable/reference/api/pandas.DataFrame.html
你好,有没有办法根据数据的性质增加下限和上限,以检测更少的异常值?
我想选择k=3用于Q1-3xIQR Q3 + 3xIQR可能是一个选项?
当然,你可以指定任何你想要的。测试一下,看看它是否提高了模型技能。
是的,您可以根据统计数据、领域知识或一时兴起设置任何您喜欢的边界。
很棒的教程,感谢您出色的工作,先生。只想分享一个小技巧……使用sklearn我们可以用这3行代码分割并返回x-train,x_test。例如在波士顿房价数据案例中
from sklearn.datasets import load_boston
x, y = load_boston(return_X_y=True)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.33, random_state=23)
不客气。
感谢分享。
深度学习中是否需要去除异常值?
这取决于数据和模型。
用你的模型和数据尝试去除和不去除异常值,然后发现最适合你的方法。
你好,
我们可以多次应用IQR规则吗?是否推荐这样做?
你可以对每个变量都使用它。
嗨,Jason,
我在相同的MLP模型上测试了两种缩放方法(MinMaxScaler和RobustScaler)。使用MinMaxScaler模型预测得很好,但使用RobustScaler则表现不佳。原因可能是什么?
原因将是输入数据上使用的缩放方法的差异。
如果你想知道为什么神经网络会受到输入尺度影响,那么可以看看这里
https://machinelearning.org.cn/how-to-improve-neural-network-stability-and-modeling-performance-with-data-scaling/
感谢您提供如此精彩的内容。不过,我很好奇,在多变量数据集中,哪种方法在综合考虑所有特征的情况下效果最好。
很多模型都有效。你尝试了什么?如果你的数据不是很复杂,可以先尝试决策树或SVM。
我喜欢阅读您的文章。我真的很喜欢阅读。解释得非常清楚。谢谢您
尊敬的Jason博士,我有一个包含14个数值特征的数据框。我能够检测到异常值。但我不知道什么时候删除包含异常值的行是安全的。考虑到我有14个特征,我删除了每行包含7个或更多异常值的行。我的推理正确吗?任何建议都会有帮助。感谢您的辛勤工作。
正确——但也要尝试计算你删除的行数。根据异常值的定义,我不期望整个数据集的20%(例如)是异常值。
一如既往的精彩文章!
能否请您撰写一篇关于“检测和移除分类特征异常值”的文章?