当前位置:   article > 正文

中对缺失数据的预处理_数据预处理中重要的一环:离群值监测和处理

散点图有一个数据明显偏离

全文共6023字,预计学习时长20分钟或更长

0dd1fd5454447b68711a89a70b3a2bfe.png

来源:Pexels

离群值监测和处理是数据预处理中最重要的环节之一。机器学习算法注重数据点的范围和分布,而数据离群值掩盖训练进程,导致训练时间加长、模型准确性降低。离群值是与其余数据明显不同的数据点,这些数值分布于整体模型之外。而平均值、方差、相关量等统计度量均易受离群值的影响。

以下是一个简单的离群值举例,可以看到有一个数据点明显偏离整体模型:

1f3a9257e93006181fb00f91ba85e42e.png
15ef03319e2801341407e5363e0f1d75.png

离群值属性

数据集中出现离群值可能是以下原因之一:

1. 某个数据集中确实存在的极高值或极低值

2. 由于人类或机器的错误而产生

3. 由替换缺失值产生

有时候,离群值的存在可以反映很多信息,需要进一步研究。例如,离群值在交易管理相关的用例中就很重要,因为离群值在交易管理中可以识别潜在的诈骗交易。

ae55cda95c52d84ea9bd4c25f56c6d19.png

来源:Pexels

本文将对以下识别和处理数据集中离群值的方法进行讨论。

离群值检验

· 极值分析

· Z分数法(Z-score)

· k均值聚类算法

· 可视化数据

离群值处理

· 平均值/中位数或随机缺失值处理

· 修整

· 顶端、底端编码和零编码

· 离散化

然而,以上的几种方法均不能证实哪个观测值是真正的离群值。目前关于离群值的构成还没有严格的数学定义,确定某个观测值是否为离群值基本上也是我们的主观行为,这很大程度上取决于某个特定的商业问题。因此,本文讨论的这些方法只是检测过程的开端,帮助大家识别数据中应处理为离群值的数据点。

c3ff54e673130b1e42a73d4e26f83fec.png

检验离群值的方法

有很多方法可以确定数据中的离群值。本文将对以下方法进行讨论:

1. 极值分析

2. Z分数法(Z-score)

3. k均值聚类算法

有一点需要重申,这些方法不应机械地使用,而应该用这些方法深究数据本身。这些方法可以让你知道哪些数据点需要进一步研究。

数据集:

本文利用Kaggle中LendingClub Loan Dataset来演示本文的例子。

导入库

importpandas as pdimport numpy as np import seaborn as snsimport matplotlib.pyplot as plt%matplotlib inline

导入数据集

现在,从csv文件中输入年收入(annual_inc)列,识别离群值。

use_cols = ['annual_inc']data = pd.read_csv('loan.csv', usecols=use_cols, nrows = 30000)
ebcb873e6bbd51fced0b8b3ebae09db7.png

极值分析

离群值检验最基础的方法就是极值分析。该法关键在于确定变量基本分布的统计低点,找出极低值。

就高斯分布而言,离群值会高于或低于平均值3倍变量标准差。

990ce394760dbb13dedc6091be53fc7e.png

若变量非正态分布(不是高斯分布),那么就可以采取计算分位数和四分位数间距范围的方法。

db8508453204db08df6488ad4f6794e1.png
IQR (Inter quantiles range)= 75th quantile — 25th quantile

离群值出现在上下边界上限和下限中:

Upper Boundary = 75th quantile +(IQR * 1.5)Lower Boundary = 25th quantile — (IQR * 1.5)

或为极值:

Upper Boundary = 75th quantile +(IQR * 3)Lower Boundary = 25th quantile — (IQR * 3)

如若数据点在上限之上或下限之下,即可视为离群值。

代码:

首先,计算数据集四分位数间距范围:

IQR = data.annual_inc.quantile(0.75) - data.annual_inc.quantile(0.25)

依据上述提到的公式,利用四分位数间距(IQR),计算上界:

upper_limit = data.annual_inc.quantile(0.75) + (IQR * 1.5)upper_limit_extreme = data.annual_inc.quantile(0.75) + (IQR * 3)upper_limit, upper_limit_extreme
b1ea7e1d80a445a66968e3d31b1d5247.png

现在,来看看上限和极上限之上的数据点比率,例如:离群值。

total = np.float(data.shape[0])print('Total borrowers:{}'.format(data.annual_inc.shape[0]/total))print('Borrowers that earn > 178k: {}'.format(data[data.annual_inc>178000].shape[0]/total))print('Borrowers that earn > 256k:{}'.format(data[data.annual_inc>256000].shape[0]/total))
76fe5d50306f8d101bbfb736cebebba4.png

可以看出,有5%的数据在上限之上,有1%的数据在极上限上。

9bc35ae5614e69f67c657edfe9a54381.png

Z分数法

Z分数(或称标准分数)表示有多少标准差(即所给出的偏离平均值的度量)。换言之,其仅仅是将数据重新调节或标准化。利用Z分数可确定分布内观测值的精准定位。Z分数可以显示数值是在平均数之上还是之下。

利用Z分数法旨在消除数据位置和大小的影响,以便直接比较不同的数据集。Z分数法检验离群值的途径就是先集中并重调数据,然后任何偏离零(通常以Z分数3或-3为临界值)太远的数值都应视为一个离群值。

计算Z分数的公式如下:

5fdf45ba00d189373299d693b3367f6b.png

代码:

导入库

from scipy import stats

计算Z分数

z = stats.zscore(data)print(z)
6e3e4e94b7d8209fc939b512aeb986a3.png

临界值>3

threshold = 3print(np.where(z > 3))
b9d6b1662568d86627159740c3619e16.png

据上述输出,第一序列包含行数字,第二序列表示列数字。

0198dc4e5d78491f489b9ef1275e1396.png

聚类分析法

聚类法是常见的方法,用于对相似数据点或同组、同集群的对象进行分组。这是离群值分析中十分重要的方法。运用此方法前,应先将相似的这类对象分组。

利用K均值聚类法帮助我们汇集数据(即我们的年度收入值),然后采用欧几里得距离(Euclidean distance)将相似对象分类。现在来试试吧!

代码:

导入库

现在,从scipy.cluster.vq.中导入K均值模数。SciPy支持科学性Python,为科学实验的实施提供各种各样的便利程序。

from scipy.cluster.vq import kmeansfrom scipy.cluster.vq import vq

将数据转换为numpy的对象Array,并应用K均值函数。同时,需给出两个输入数据,然后,集群数便形成了。

data_raw = data['disbursed_amount'].valuecentroids, avg_distance = kmeans(data_raw, 4)groups, cdist = vq(data_raw, centroids)

距心是由kmeans()形成的集群中心,avg_distance是各数据点和距心之间的欧几里得距离平均值。接下来,启动vq()法。返回数据组(集群)和数据点及其最近数据组的距离。

现在一起绘制所获得的各组数。

y = np.arange(0,30000)plt.scatter(data_raw, y , c=groups)plt.xlabel('Salaries')plt.ylabel('Indices')plt.show()
09eb44ce14a2e219cd9586fe32aa88fa.png

相信你肯定可以通过上方的图片识别出离群值。

f961c479b3b2cd7795bd309ad27fc4fe.png

图示法

如之前文章中提到的,箱线图、直方图、散点图都是一些用于识别数据集中离群值的主要方法。

箱线图

箱线图,又称Whisker图,是由分位数和四分位数间距来进行描述的图表法。它可以帮助定义上限和下限,任何超出上限和下限的数据都是离群值。

总而言之,分位数是在分布内与值顺序排列相关的点。在给出的例子中,通过样本排序即可找到分位数。所挑出样本的中间值就在分位数中间或在第50个百分位数上(又称样本中位数)。

f7aec63a845e1ebdd3dbdb93f3327960.png

箱线法的目的是在任何更进一步的分析之前识别出数据序列中的离群值,以便通过研究得出更加准确的结果,并不受任何极值和非常态值的影响。

sns.boxplot(y='annual_inc', data = data)
229feeabc76d40c4a724ef133de08b42.png

这里,离群值是那些数值上不同于其他数据的观测值。回看箱线图,离群值位于箱线图内栅栏线外(“whiskers”)。

直方图

直方图是显示数据数值以及发现数据集的分布最常用的图表之一。离群值位于整体分布模型之外。

fig = data.annual_inc.hist(bins=500)fig.set_xlim(0,500000)
8b8d597805a1c1c1c375829d4ca4caa0.png

在这里,位于X轴最右侧的数据点就是离群值。

散点图

散点图用于找到两个变量之间的联系,并且此联系常常有一种模型。不符合该模型的数据点就是离群值。

data_raw = data['annual_inc'].valuesy = np.arange(0,30000)plt.scatter(data_raw, y)plt.xlabel('Annual Income')plt.ylabel('Indices')plt.show()
4008bac24f70b4a0ee16c743dad3a7f5.png
15ef03319e2801341407e5363e0f1d75.png

预处理离群值的方法

1. 平均值/中位数/随机缺失值处理

如果有理由相信离群值是由机器错误或是计量纰漏导致的,那么就意味着离群值本质与缺失值类似,任何数据缺失处理的方法都可用于替换离群值。离群值的数字很小(否则它们不会成为离群值),用中位数、中位数、随机缺失值处理来替换离群值是合理的。

2. 修整

此法完全摒弃离群值。也就是说,消除视为离群值的数据点。由于不可能去除数据集中的大量数值,所以修整是较好较快的方法。

index = data[(data['annual_inc'] >= 256000)].indexdata.drop(index, inplace=True)

这里,先运用极值分析确定高于上限的数值,然后运用pandas的drop函数去除去除这些值。

3. 顶端编码/底端编码/零编码

顶端编码即对分布内最大值设置任意数值。顶端编码变量是超过上限且已被删除的数据点。通过执行顶端编码,离群值被限制在一个特定的最大值,该值与很多观测结果相近。

底端编码与此类似,但是在分布右侧。也就是说,所有值均在某临界值之下,受临界值限制。如若临界值为零,那么称为零编码。举个例子,像“年龄”、“收入”这类变量是没有负值的。因此,将最低值设为零也是说得通的。

代码:

print('Annual Income > 256000: {}'.format(data[data.annual_inc>256000].shape[0]))print('Percentage of outliers: {}'.format(data[data.annual_inc>256000].shape[0]/np.float(data.shape[0])))
edd28b5cd9bad62f817fd5184ec808b6.png

此步,设置数据点值大于256000。

data.loc[data.annual_inc>256000,'annual_inc'] = 256000data.annual_inc.max()

现在,最大值为256000。

4. 离散化

离散化是连续变量转换为非连续变量的过程,这个过程通过创建一组跨越变量值范围的连续区间完成。因此,这些离群观测值和其余分布尾端的值不再相同,它们都在同一个区间/范围中。

连续变量转换为非连续变量的方法有很多。此法也称为数据分箱技术,每个箱子分属于各自的区间。

离散化分析的方法:

(1)等频离散化

等频分箱将可能的变量值分为N个箱,每个箱都有相同数量的观测值。这个方法尤其对交错变量十分有用,因为它把观测值平均地置于不同的箱中。通常,通过分位数确定区间临界,这有助于减少信息缺失,得到更好的结果。

这里,我们利用pandas的qcut函数(基于分位数的离散函数)创建5个分箱。

income_discretised, intervals = pd.qcut(data.annual_inc, 5,labels=None, retbins=True, precision=3, duplicates='raise')pd.concat([income_discretised, data.annual_inc], axis=1).head(5)
755a4a277c31a26561a462b7fdfbf8d2.png

区间是:

intervals
65883b6f83d460167cc0a5167e1f5615.png

下面,可以看到每个区间都有几乎相同数量的观测值。

temp = pd.concat([income_discretised, data.annual_inc], axis=1)temp.columns = ['income_discretised', 'annual_inc']temp.groupby('income_discretised')['annual_inc'].count()
f5912bb3dde523b38655554504392e76.png

(2)等宽离散化

等宽离散分箱将可能值的范围分为N个等宽箱。宽度取决于变量值的范围和我们期望变量的分箱数。

宽=(最大值-最小值)/N

举个例子,如果变量的值在0~100,就要创建5个这样的宽度的箱子:宽=(100-0)/5=20。此时,第一个箱子0~20和最后一个箱子80~100可扩展用于放置离群值(也就是说,0以下和100以上的值可以放置在这两个箱子中)。目前无法凭经验来定义N,仍需依赖实际用例来定义。

代码:

income_range = data.annual_inc.max() - data.annual_inc.min()min_value = int(np.floor(data.annual_inc.min()))max_value = int(np.ceil(data.annual_inc.max())) # let's round the bin widthinter_value = int(np.round(income_range/5)) min_value, max_value, inter_value
7c68747e8ad5b9e6dc1e220ffca038b2.png

现在,计算区间:

intervals = [i for i in range(min_value, max_value+inter_value, inter_value)]labels = ['Bin_'+str(i) for i in range(1,len(intervals))]print(intervals)print(labels)
f45bd05f080f3c4f7e142c3727cf86cf.png

最后,利用pandas的cut函数切割整理数据值到各箱中:

data['annual_inc_labels'] = pd.cut(x = data.annual_inc,bins=intervals, labels=labels, include_lowest=True)data['annual_inc_interval'] = pd.cut(x = data.annual_inc,bins=intervals, include_lowest=True)data.head(5)

可利用如下所示的统计图计量每个箱中的数据。可以看出,给定的样本数据中,大多数人的收入都低于10000。

0b4fb91ec0e389d5255af0f335854d39.png
sns.countplot(data.annual_inc_labels)
7f41249a03c57e22de64c461426abaa6.png
d126c06303cf8c9ef52fa7e6c400659c.png

留言 点赞 关注

我们一起分享AI学习与发展的干货

欢迎关注全平台AI垂类自媒体 “读芯术”

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/301941
推荐阅读
相关标签
  

闽ICP备14008679号