在建模时,对数据惊醒清理以确保观察结果可以很好地代表问题是很重要的。有时,数据集可能包含超出预期范围的,与其他值不同的极端值,这些值被称为离群值。通常可以通过理解甚至去除这些离群值,来提高机器学习建模和模型技巧。

在本教程中,你将学到如何从机器学习数据集中识别和删除离群值。

完成本教程后,你将学到:

  • 离群值在数据集中是不太可能观察到,这可能有多种原因。


  • 如何使用简单的单变量统计数据,如标准差和四分位数,来识别和移除数据样本中的异常值。


  • 如何使用离群点检测模型来识别和移除训练数据集中的离群值,以提高预测建模的性能。



什么是离群值?

离群值是一种不同于其他观测值的观测值。它是少见的,或独特的。

测试数据集

在研究离群值识别方法之前,我们先定义一个用于测试这些方法的数据集。我们将从均值为50,标准差为5的高斯分布中生成1万个随机数字。从高斯分布中得出的数字会有离群值。也就是说,根据分布本身,会有一些离均值很远的值,我们可以识别为离群值。
#generate Gaussian datafrom numpy.random import seed, randnfrom numpy import mean, std#seed the random number generatorseed(1)#generate univariate observationsdata = 5*randn(10000)+50#summarizeprint('mean=%.3f stdv=%.3f' % (mean(data), std(data)))
标准差法(Standard Deviation Method)

如果我们知道样本中的分布是高斯分布,我们可以使用样本的标准差作为一个截止点来识别离群值。

高斯分布具有用偏离均值的标准差距离来计算样本值的在分布中百分位的性质。例如,均值的一个标准差内将覆盖68%的数据。因此,如果平均值是50,标准偏差是5,如上面的测试数据集,在45到55之间的样本将占数据样本总体的68%左右。如果我们将范围扩大如下,我们可以覆盖更多的数据样本:

离均值的1个标准差为68%,离均值2个标准差为95%,离均值3个标准差为99.7%。3个标准差以外的值是分布的一部分,但通常是不太可能或罕见的,可视为离群值。

在实践中,在高斯分布或类高斯分布中识别异常值时,离均值三个标准差是一个常见的截止点。对于较小样本的数据,可能使用2个标准差(95%),对于较大样本,可能使用4个标准差(99.9%)作为截止点。
#calculate summary statisticsdata_mean, data_std = mean(data), std(data)#identify outlierscut_off = data_std * 3lower, upper = data_mean -cut_off, data_mean + cut_off
然后,我们可以识别出那些在定义的下限和上限之外的离群值。
# identify outlieroutliers = [x for x in data if x < lower or x > upper]# remove outlieroutliers_removed = [x for x in data if x > lower and x < upper]print('Non-outlier observations: %d' % len(outliers_removed))
到目前为止,我们只讨论了高斯分布的单变量数据,例如单个变量。如果你有多元数据,你可以使用同样的方法,例如,数据有多个变量,每个变量有不同的高斯分布。你可以想象二维空间的边界,如果你有两个变量,就可以定义一个椭圆。落在椭圆之外的观测将被认为是异常值。在三维空间中,这是一个椭球,以此类推进入更高的维度。另外,如果你对该领域了解更多,那么可能会通过超出数据维的一个或一个子集的限制来标识离群值。

四分位范围法(Interquartile Range Method)

并不是所有的数据都是高斯分布。汇总非高斯分布样本的一个很好的统计量是四分位数范围,简称IQR。IQR是作为数据的第75和第25百分位数之间的差值计算的。

请记住,百分数可以通过对观察数据进行排序并在特定分位上选择值来计算。第50百分位是中间值,或者是偶数个例子中两个中间值的平均值。如果我们有10,000个样本,那么第50百分位将是第5000个和第5001个值的平均值。
# identify outliers with interquartile rangefrom numpy.random import seedfrom numpy.random import randnfrom numpy import percentile# seed the random number generatorseed(1)# generate univariate observationsdata = 5 * randn(10000) + 50# calculate interquartile rangeq25, q75 = percentile(data, 25), percentile(data, 75)iqr = q75 - q25print('Percentiles: 25th=%.3f, 75th=%.3f, IQR=%.3f' % (q25, q75, iqr))# calculate the outlier cutoffcut_off = iqr * 1.5lower, upper = q25 - cut_off, q75 + cut_off# identify outliersoutliers = [x for x in data if x < lower or x > upper]print('Identified outliers: %d' % len(outliers))# remove outliersoutliers_removed = [x for x in data if x >= lower and x <= upper]print('Non-outlier observations: %d' % len(outliers_removed))
自动异常值检测(Automatic Outlier Detection

在机器学习中,解决离群点检测问题的一种方法是单类分类。单类分类(one-class classification),简称OCC,涉及到对“正常”数据拟合模型,并预测新数据是正常数据还是异常数据。

单类分类器是在正常值的训练数据集上训练的。一旦训练好,模型被用来对新的例子分类,分为正常值或异常值。

识别离群点的一种简单方法是在特征空间中定位那些与其他样本距离较远的样本。这对于低维度(很少特征)的特征空间可以很好地工作,尽管随着特征数量的增加,它可能变得不那么可靠,这被称为维数诅咒。

scikit-learn库在LocalOutlierFactor类中提供了这种方法的实现。我们可以在一个预测建模数据集上演示LocalOutlierFactor方法。我们将使用波士顿住房数据集,该问题有13个预测变量和一个响应变量,需要学习郊区特征和房价之间的关系。
# load and summarize the datasetfrom pandas import read_csvfrom sklearn.model_selection import train_test_split# load the dataseturl = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'df = read_csv(url, header=None)# retrieve the arraydata = df.values# split into inpiut and output elementsX, y = data[:, :-1], data[:, -1]# summarize the shape of the datasetprint(X.shape, y.shape)# split into train and test setsX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)# summarize the shape of the train and test setsprint(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
运行上面代码会加载数据集,报告数据集中的行数和列数,报告分配给训练和测试数据集的示例的数据数。

这是一个回归预测建模问题,意味着我们将预测一个数值。所有的输入变量也都是数字。在这种情况下,我们将拟合一个线性回归模型,通过在测试数据集上训练模型,对测试数据进行预测,并使用平均绝对误差(mean absolute error, MAE)对预测结果进行评估,来评估模型的性能。评估模型的代码如下:
# evaluate model on the raw datasetfrom pandas import read_csvfrom sklearn.model_selection import train_test_splitfrom sklearn.linear_model import LinearRegressionfrom sklearn.metrics import mean_absolute_error# load the dataseturl = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'df = read_csv(url, header=None)# retrieve the arraydata = df.values# split into inpiut and output elementsX, y = data[:, :-1], data[:, -1]# split into train and test setsX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)# fit the modelmodel = LinearRegression()model.fit(X_train, y_train)# evaluate the modelyhat = model.predict(X_test)# evaluate predictionsmae = mean_absolute_error(y_test, yhat)print('MAE: %.3f' % mae)
接下来,我们可以尝试从训练数据集中移除异常值。

我们的期望是,这些离群值会导致线性回归模型对问题的理解出现偏差或偏斜,并且从训练集中删除这些离群值将会学习一个更有效的模型。

我们可以通过定义LocalOutlierFactor,并使用它对训练数据集进行预测,将训练数据集中的每一行标记为normal(1)或离群值(-1)来实现这一点。我们使用离群点检测模型的默认超参数。
# identify outliers in the training datasetlof = LocalOutlierFactor()yhat = lof.fit_predict(X_train)# select all rows that are not outliersmask = yhat != -1X_train, y_train = X_train[mask, :], y_train[mask]# evaluate model on training dataset with outliers removedfrom pandas import read_csvfrom sklearn.model_selection import train_test_splitfrom sklearn.linear_model import LinearRegressionfrom sklearn.neighbors import LocalOutlierFactorfrom sklearn.metrics import mean_absolute_error# load the dataseturl = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'df = read_csv(url, header=None)# retrieve the arraydata = df.values# split into inpiut and output elementsX, y = data[:, :-1], data[:, -1]# split into train and test setsX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)# summarize the shape of the training datasetprint(X_train.shape, y_train.shape)# identify outliers in the training datasetlof = LocalOutlierFactor()yhat = lof.fit_predict(X_train)# select all rows that are not outliersmask = yhat != -1X_train, y_train = X_train[mask, :], y_train[mask]# summarize the shape of the updated training datasetprint(X_train.shape, y_train.shape)# fit the modelmodel = LinearRegression()model.fit(X_train, y_train)# evaluate the modelyhat = model.predict(X_test)# evaluate predictionsmae = mean_absolute_error(y_test, yhat)print('MAE: %.3f' % mae)
运行上面的代码,用从训练数据集中删除的离群值来拟合和评估线性回归模型。你会发现模型的性能会有所提升。

Scikit-Learn库提供了其他离群点检测算法,可以以相同的方式使用,如IsolationForest算法。有关自动离群值检测的更多示例,可以去探索Scikit-Learn库。
回复

使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    560

    主题

    1399

    帖子

    3378

    积分

    论坛元老

    Rank: 8Rank: 8

    积分
    3378
    发表于 2021-3-12 21:04:06 | 显示全部楼层
    沙发
    如果对python感兴趣,如果对机器学习感兴趣,这是很好的教程!
    回复

    使用道具 举报

    500

    主题

    1301

    帖子

    3130

    积分

    论坛元老

    Rank: 8Rank: 8

    积分
    3130
    发表于 2021-3-12 21:04:49 | 显示全部楼层
    板凳
    收藏
    回复

    使用道具 举报

    549

    主题

    1441

    帖子

    3453

    积分

    论坛元老

    Rank: 8Rank: 8

    积分
    3453
    发表于 2021-3-12 21:05:22 | 显示全部楼层
    地板
    转发了
    回复

    使用道具 举报

    545

    主题

    1341

    帖子

    3263

    积分

    论坛元老

    Rank: 8Rank: 8

    积分
    3263
    发表于 2021-3-12 21:05:27 | 显示全部楼层
    5#
    转发了
    回复

    使用道具 举报

    532

    主题

    1341

    帖子

    3244

    积分

    论坛元老

    Rank: 8Rank: 8

    积分
    3244
    发表于 2021-3-12 21:06:05 | 显示全部楼层
    6#
    转发了
    回复

    使用道具 举报

    569

    主题

    1437

    帖子

    3457

    积分

    论坛元老

    Rank: 8Rank: 8

    积分
    3457
    发表于 2021-3-12 21:06:20 | 显示全部楼层
    7#
    转发了
    回复

    使用道具 举报

    • 售后服务
    • 关注我们
    • 社区新手

    QQ|手机版|小黑屋|数据通

    Powered by datatong.net X3.4  © 2008-2020 数据通