乐趣区

关于机器学习:使用可视化工具和统计方法检测异常值

异样值(离群值)是指间隔其余数据值太远的数据值。数据异样值可能是天然产生的,也可能是因为测量不精确、或系统故障造成的。与缺失值相似,异样值会毁坏数据迷信我的项目并返回谬误的后果或预测。异样值也可能呈现在歪斜数据中,这些类型的异样值被认为是天然异样值。

异样值会影响数据的平均值、标准差和四分位范畴。如果咱们在去除异样值之前和之后计算这些统计数据,咱们会失去不同的后果。

异样值如何影响机器学习模型?

如果咱们的异样值是天然的而不是因为测量误差,则应该将它保留在数据集中,并执行数据转换来对其进行规范化解决。如果咱们的数据集很大,但异样值很少,咱们应该保留这些异样值,因为它们不会显著影响后果,并且能够为咱们的模型带来泛化的成果。

如果咱们十分确定我异样值是因为测量误差带来的,则应该从数据集中删除它们。去除异样值的将缩小数据集的大小,并能够让咱们的模型的实用到所蕴含的度量范畴。然而要记住去掉天然异样值可能导致模型不精确。

应用可视化工具检测异样值

异样值是不容易被“肉眼”发现的,然而有一些可视化工具能够帮忙实现这项工作。最常见的是箱形图和直方图。

和平常一样,咱们第一步是加载必要的库和导入 / 加载数据集。这里将应用 insurance.csv(https://www.kaggle.com/datase…)。

 import numpy as np
 import pandas as pd
 import seaborn as sns
 import statistics
 
 df = pd.read_csv('insurance.csv')
 df

咱们将查看 age,bmi 和 expenses 的异样值。

第一种办法是用 box – plot 示意数据分布:

 sns.boxplot(y="age", data=df)
 sns.boxplot(y="bmi", data=df)
 sns.boxplot(y="expenses", data=df)

从箱线图咱们能够看到 age 没有异样值 bmi 在上界有一些异样值,而 expenses 在上界有很多异样值,这表明了这是一个偏态散布。为了查看这个偏态散布的歪斜水平,咱们将应用直方图。

 sns.histplot(df, x="age", kde=True)
 sns.histplot(df, x="bmi", kde=True)
 sns.histplot(df, x="expenses", kde=True)

从直方图中能够看出,年龄变量均匀分布,bmi 靠近正态分布,expenses 偏态散布。通过剖析这两种图形示意,咱们能够决定要排除那些数据。对于年龄不排除任何值。对于 bmi 咱们将排除高于 47 的值,对于费用,咱们将排除高于 50000 的值。

 df.drop(df[df['bmi'] >= 47].index, inplace = True)
 df.drop(df[df['expenses'] >= 50000].index, inplace = True)

当初如果再次查看箱线图和直方图:

用统计办法检测异样值

有两种次要的统计办法能够检测异样值: 应用 z 分数和应用四分位范畴。

1、应用 Z -score 检测异样值

Z-score 是一种数学变换,依据其与均值的间隔对每个察看后果进行分类。与平均值之间的间隔用标准差 (SD) 来掂量。如果失去的数值为 1.59,咱们就晓得察看值比平均值高出 1.59 个标准差。同理如果失去 -2.4 的 Z -score,咱们就会晓得察看值比平均值低 -2.4 个标准差。高于 3SD 或低于 -3SD 的观测值个别会被认为是异样值。

上面咱们用代码实现,首先查看 age:

 df = pd.read_csv('insurance.csv')
 mean_age = statistics.mean(df['age'])
 stdev_age = statistics.stdev(df['age'])
 
 age_z_score = (df['age']-mean_age)/stdev_age
 df['age_z_score'] = age_z_score.tolist()

当初查看是否有低于 -3SD 的值:

 df.sort_values(by=['age_z_score'], ascending=True)

能够看到没有低于 -3SD 的值。当初查看 3SD 以上的值:

咱们能够看到没有高于 3SD 的值。也就是说 age 没有异样值。当初对变量 bmi 做同样的操作:

 mean_bmi = statistics.mean(df['bmi'])
 stdev_bmi = statistics.stdev(df['bmi'])
 bmi_z_score = (df['bmi']-mean_bmi)/stdev_bmi
 df['bmi_z_score'] = bmi_z_score.tolist()
 
 df.sort_values(by=['bmi_z_score'], ascending=True)
 df.sort_values(by=['bmi_z_score'], ascending=False)

查看 3SD 以上的值:

将这些值删除:

 df.drop(df[df[‘bmi_z_score’] >= 3].index, inplace = True)

下一步用同样的办法计算 expenses:

 mean_expenses = statistics.mean(df['expenses'])
 stdev_expenses = statistics.stdev(df['expenses'])
 expenses_z_score = (df['expenses']-mean_expenses)/stdev_expenses
 df['expenses_z_score'] = expenses_z_score.tolist()
 
 df.sort_values(by=['expenses_z_score'], ascending=True)
 df.sort_values(by=['expenses_z_score'], ascending=False)
 df.drop(df[df[‘expenses_z_score’] >= 3].index, inplace = True)

删除了数据当前,咱们再次可视化数据:

能够看到,一些值曾经被移除了

2、应用四分位距检测异样值

四分位距将数据分布到四个局部,并且从低到高排序,如下图所示,每个局部蕴含雷同数量的样本。第一个四分位 (Q1) 是边界上的数据点的值。Q2 和 Q3 也是如此。四分位距 (IQR) 是两个两头局部的数据点 (代表 50% 的数据)。四分位距蕴含所有高于 Q1 低于 Q3 的数据点。如果该点高于 Q3 + (1.5 x IQR),则示意蕴含较高数值离群值,如果 Q1−(1.5 x IQR) 则存在较低数值的离群值。

代码如下:

 df = pd.read_csv('insurance.csv')
 q75_age, q25_age = np.percentile(df['age'], [75 ,25])
 iqr_age = q75_age - q25_age
 iqr_age
 
 age_h_bound = q75_age+(1.5*iqr_age)
 age_l_bound = q25_age-(1.5*iqr_age)
 print(age_h_bound)
 print(age_l_bound)

这样就晓得了异样值位于 87 以上或 - 9 以下:

 df.sort_values(by=['age'], ascending=True)

能够看到没有下异样值,当初咱们将查看上异样值:

 df.sort_values(by=['age'], ascending=False)

也没有上异样值。

上面对 bmi 执行同样的操作:

 q75_bmi, q25_bmi = np.percentile(df['bmi'], [75 ,25])
 iqr_bmi = q75_bmi - q25_bmi
 iqr_bmi
 
 bmi_h_bound = q75_bmi+(1.5*iqr_bmi)
 bmi_l_bound = q25_bmi-(1.5*iqr_bmi)
 print(bmi_h_bound)
 print(bmi_l_bound)
 
 df.sort_values(by=['bmi'], ascending=True)
 df.sort_values(by=['bmi'], ascending=False)
 
 df.drop(df[df['bmi'] >= 47.3].index, inplace = True)
 df.drop(df[df['bmi'] <= 13.7].index, inplace = True)

expenses 也是用雷同的办法进行解决,咱们对后果进行可视化:

能够看到异样值也被删除了

https://avoid.overfit.cn/post/c55c9a078cf44e33912c6f98affdd7c4

作者:Carla Martins

退出移动版