作者 | SHAILESH SHUKLA    编译 | Flin    来源 | analyticsvidhya

介绍

你在处理异常值吗?哪种方法更适合检测偏斜或正态分布数据的异常值?

伙计们,无论你是在执行 EDA 之前进行数据清理过程,将数据传递给机器学习模型,还是执行任何统计测试,本文都将帮助你获得许多此类问题的答案以及实际应用。

什么是Inliers和Outliers?

Outliers(异常值)是看起来与给定数据集中的大多数其他值有很大差异的值异常值通常可能是由于新发明(真正的异常值)、新模式/现象的发展、实验错误、很少发生的事件、异常、由于排版错误导致的错误输入数据、数据记录系统/组件故障等而出现的。

Inliers(正常值)是除异常值之外的分布中的所有数据点。

异常值的识别

全局或点异常值: 偏离分布的单个值/数据点,大多数异常值检测方法通常旨在检测点/全局异常值。

集合异常值:当一组数据点偏离分布时,称为集合异常值。根据特定领域来解释它们的相关性是完全主观的。此外,集合异常值表明新现象或发展的形成。

上下文异常值:这些是基于对其相关性的解释的特定条件,例如语音识别技术中的单一背景噪声。

图1:点/全局或集体异常值

为了便于理解,我举了一个例子:关于三年内废钢销售的真实案例研究。

离群值的真实案例

考虑到 2018 年至 2022 年在印度各地销售的钢板废品率 (Rs/Kg) 的真实情况,我们已捕获以了解统计数据并预测未来的价格。尽管如此,在此之前,作为数据清理过程的一部分,我们希望了解异常值的存在及其相应的权重。

导入重要库以加载数据集并进行进一步分析:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import scipy.stats as st
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
df=pdf.read_excel("scrap_data.xlsx", skiprows=2)
df.head(), print('shape of data:',df.shape)

为了了解趋势,我尝试在两个主要的自变量(‘Scrap Rate’ and ‘Scrap Weight’)上绘制线图,并参考其销售日期。

plt.figure(figsize =(15,5))
plt.subplot(1,2,1)
sns.lineplot(x=df['Job Start Date'], y=df['Rate in Rs./Kg.'], color='r')plt.title("Steel Scrap Rate (Rs/Kg)", fontsize=20)
plt.xlabel('Date')plt.subplot(1,2,2)
sns.lineplot(x=df['Job Start Date'], y=df['Scrape Sale Qty.'], color='b')plt.title("Steel Scrap Weight (Rs/Kg)", fontsize=20)
plt.xlabel('Date')

从废品率特征的趋势来看,我们了解到超过 120 Rs/kg 的费率突然飙升,这表明了异常情况的产生,因为一般来说,废品率必须相同并且逐渐增加或减少。但是,就废品重量而言,根据建设项目的规模,在项目结束时产生的废品量随时可能高或低。

让我们尝试应用检测和处理异常值的不同方法。

四分位间距 (IQR)

IQR 通过将数据集分成四个相等的四分位数来测量变异性。首先,将整个数据按升序排序,然后将其分成四个相等的四分位数,分别称为 Q1、Q2、Q3 和 Q4,可以使用以下等式计算。当数据形成偏态分布时,IQR 方法最适合。

第一个四分位数 (Q1) 将最小的 25% 的值与其他 75% 的较大值相除。

Q1 = (n+1)/4 排名值(第 25 个百分位)

第三分位数 (Q3) 将最小的 75% 与最大的 25% 相除。

Q3 = 3(n+1)/4 排名值(第 75 个百分位)

IQR(分位数范围)= Q3– Q1

下限 = Q1 – 1.5 x IQR

上限 = Q3 + 1.5 x IQR

因此,可以将异常值视为给定数据集中大于上限 (Q3+1.5*IQR) 且小于下限 (Q1-1.5*IQR) 的任何值。

让我们绘制箱线图以了解异常值的存在;

plt.figure(figsize=(15,5))
plt.subplot(1,2,1)
sns.boxplot(df['Scrape Sale Qty.'])
plt.xticks(fontsize = (12))
plt.xlabel('Steel-Scrap Weight (in Kgs)')
plt.legend (title="Steel Scrap Weight", fontsize=10, title_fontsize=15)
plt.subplot(1,2,2)
sns.boxplot(df['Rate in Rs./Kg.'])
plt.xlabel('Steel Scrap Rate Rs/kg')
plt.xticks(fontsize =(12));
plt.legend (title="Steel Scrap Rate", fontsize=10, title_fontsize=15);

为了使计算更快,我创建了一个函数来导出四分位数范围 (IQR)、下限和上限,并添加了分别删除它们或用上限值或下限值填充它们的条件。

def identifying_treating_outliers(df,col,remove_or_fill_with_quartile):q1=df[col].quantile(0.25)q3=df[col].quantile(0.75)iqr=q3-q1lower_fence=q1-1.5*(iqr)upper_fence=q3+1.5*(iqr)print('Lower Fence;', lower_fence)print('Upper Fence:', upper_fence)print('Total number of outliers are left:', df[df[col]  upper_fence].shape[0])if remove_or_fill_with_quartile=="drop":df.drop(df.loc[df[col]<lower_fence].index,inplace=True)df.drop(df.loc[df[col]>upper_fence].index,inplace=True)elif remove_or_fill_with_quartile=="fill":df[col] = np.where(df[col] < lower_fence, lower_fence, df[col])df[col] = np.where(df[col] > upper_fence, upper_fence, df[col])

将函数应用于 Scrap Rate 和 Scrap Weight 列:

identifying_treating_outliers(df,'Scrape Sale Qty.','drop')
identifying_treating_outliers(df,'Rate in Rs./Kg.','drop')

应用函数前的 DF 形状 : (1001, 5)

应用函数后的 DF 形状 : (925, 5)

在应用 'indentifying_treating_outliers' 函数后绘制箱线图以检查异常值的状态:

plt.figure(figsize=(15,5))
plt.subplot(1,2,1)
sns.boxplot(df['Scrape Sale Qty.'])
plt.xticks(fontsize = (12))
plt.xlabel('Steel-Scrap Weight (in Kgs)')
plt.legend (title="Steel Scrap Weight", fontsize=10, title_fontsize=15)
plt.subplot(1,2,2)
sns.boxplot(df['Rate in Rs./Kg.'])
plt.xlabel('Steel Scrap Rate Rs/kg')
plt.xticks(fontsize =(12));
plt.legend (title="Steel Scrap Rate", fontsize=10, title_fontsize=15);

使用 IQR 方法,我们分别从废品率 (Rate > 34 Rs/kg) 和废品重量 (>1503 kg) 中删除了 15 个数据点和 65 个数据点。删除的观察总数为 76。

Z 分数法

值的 Z 分数是该值与平均值之间的差值除以标准差。如果特定数据点的 Z 分数值小于 -3 或大于 +3,则 Z 分数有助于通过值识别异常值。Z 分数可以在数学上表示为;

x=特定值, μ=平均值, σ=标准偏差

下图表示使用 Z 分数将数据从正态分布转换为标准正态分布,此处给出了参考文献。

在我们的数据集中,我们将对 Zscore 大于 +3 且小于 -3 的异常值应用 Zscore。只需几行代码就可以帮助我们获得 Zscore,我们可以使用分布图(之前和之后)看到差异。

# Applying Zscore in Scrap Rate column defining dataframe by dfn
zr = st.zscore(df['Rate in Rs./Kg.'])
dfn = df[(zr-3)]# Applying Zscore in Steel Weight Column defining dataframe by dfnf
zw= st.zscore(dfn['Scrape Sale Qty.'])
dfnf = dfn[(zw-3)]
plt.figure(figsize=(12,5))
plt.subplot(1,2,1)
sns.distplot(df['Rate in Rs./Kg.'])
plt.title('Z Score Plot Before Removing Outlier',fontsize=15)
plt.subplot(1,2,2)
sns.distplot(st.zscore(dfn['Rate in Rs./Kg.']))
plt.title('Z Score Plot After Removing Outlier',fontsize=15)

我们的数据形成了一个正偏态分布(偏度值 - 0.874),在上述曲线中,该分布不能被视为近似正态分布。对比应用Zscore前后显示的曲线图,可以看到显著的改善。

print('before df shape', df.shape)
print('After df shape for Observation dropped in Scrap Rate', dfn.shape)
print('After df shape for observation dropped in weight', dfnf.shape)

使用 Z Score 方法,在 Scrap Rate 和 Scrap Weight 列中,我们删除了 Zscore -3 的 21 个数据点(3 个来自 Scrap Rate列,18 个来自 Scrap Weight列)。

局部异常值查找器 (LOF)

Local Outlier Finder 是一种无监督机器学习技术,用于根据数据点的最近邻域密度检测异常值,并且在数据集的分布(密度)不同时效果很好。LOF 基本上考虑了 K 距离(点之间的距离)和 K 邻居(点集位于 K 距离(半径)的圆内)。

Lof 考虑了两个主要参数:

(1) n_neighbors:默认值为 20 的邻居数

(2) Contamination:给定数据集中异常值的比例,可以设置为“auto”或浮点值 (0, 0.02 , 0.005)。

导入重要库并定义模型

from sklearn.neighbors import LocalOutlierFactor
d2 = df.values #converting the df into numpy array
lof = LocalOutlierFactor(n_neighbors=20, contamination='auto')
good = lof.fit_predict(d2) == 1
plt.figure(figsize=(10,5))
plt.scatter(d2[good, 1], d2[good, 0], s=2, label="Inliers", color="#4CAF50")
plt.scatter(d2[~good, 1], d2[~good, 0], s=8, label="Outliers", color="#F44336")
plt.title('Outlier Detection using Local Outlier Factor', fontsize=20)
plt.legend (fontsize=15, title_fontsize=15)

在我们的例子中,我将污染设置为“auto”(参见上图)以查看结果,发现 LOF 的性能不佳,因为我的数据传播(密度)没有太大偏差。此外,我尝试了 0.005、0.01、0.02、0.05 和 0.09 的不同污染值,但性能并不是那么好。

用于噪声应用的基于密度的空间聚类 (DBSCAN)

当我们的数据集足够大并且具有多个数字特征(多变量)时,使用 IQR、Zscore 或 LOF 处理异常值变得很困难。在这里,SK-Learn 库 DBSCAN 可以帮助我们处理多变量数据集的异常值。

DBSCAN 考虑两个主要参数(如下所述)与最近的数据点形成一个集群,并根据高密度或低密度区域检测 Inliers 或 outliers。

(1) Epsilon(我们可以根据k-距离图计算的数据点的半径)

(2) Min_samples(Epsilon(半径)中要考虑的数据点数量,取决于领域知识或专家建议)

然而,在我们的例子中,我们没有超过 5 个特征,我们只是从中选择了两个重要的数字特征来应用我们的学习并对其进行可视化。由于目前技术和人脑在完全可视化多维数据方面的限制,我们正在将 DBSCAN 应用于我们的数据集。

导入库并拟合模型。为了消除数据集中的噪声,我们使用 Min-Max Scaler 对数据进行了归一化。

from sklearn.cluster import DBSCAN
from sklearn.preprocessing import MinMaxScaler
mms = MinMaxScaler()
df[['Scrape Sale Qty.','Rate in Rs./Kg.']] = mms.fit_transform(df[['Scrape Sale Qty.','Rate in Rs./Kg.']])
df.head()
from sklearn.neighbors import NearestNeighbors
neigh = NearestNeighbors(n_neighbors=2)
nbrs = neigh.fit(df[['Scrape Sale Qty.', 'Rate in Rs./Kg.']])
distances, indices = nbrs.kneighbors(df[['Rate in Rs./Kg.', 'Rate in Rs./Kg.']])
# Plotting K-distance Graph
distances = np.sort(distances, axis=0)
distances = distances[:,1]
plt.figure(figsize=(8,5))
plt.plot(distances)
plt.title('K-distance Graph',fontsize=20)
plt.xlabel('Data Points sorted by distance',fontsize=14)
plt.ylabel('Epsilon',fontsize=14)
plt.show()

上图显示最大 Epsilon 值接近 0.08,对于样本量(我们希望在每个数据点的 epsilon 值内的点数),我们现在选择 10。

model = DBSCAN(eps = 0.08, min_samples = 10).fit(data)
colors = model.labels_
plt.figure(figsize=(10,7))
plt.scatter(df['Rate in Rs./Kg.'], df['Scrape Sale Qty.'], c = colors)
plt.title('Outliers Detection using DBSCAN',fontsize=20)

DBSCAN 技术使用基于密度的空间聚类有效地检测了显着的异常值,如下图所示。

结论

在这里,我们经历了从数据集中检测异常值的四种方法,在真实世界数据集上找到了它们的实现,并观察了不同的结果。然而,这些方法的应用还取决于数据集的大小、分布和上下文(单变量、双变量或多变量)。所有这些技术都有一定的优点和缺点。

  • IQR是最简单和最能用数学解释的技术。单变量和双变量数据可以很好地识别异常值,因为它将中值视为离散值的度量来检测极值,但在处理大量数字特征时仅限于多变量数据集。

    在我们的案例中,我们通过定义一个检测和处理异常值的函数来应用它,并将 76 个丢弃的数据点检测为异常值。

  • Zscore 衡量原始数据与标准差单位中的平均值的距离,并且比其在正态分布数据集中的应用具有优势,但是当数据集不对称(左偏或右偏)时,Zscore 技术可能会导致错误的结果.

    我们将其应用于我们的数据集,该数据集似乎略微偏斜,并检测到 21 个数据点作为潜在的异常值。

  • LOF(局部Ourliter Factor)在数据分布(密度)在整个空间中分布不均匀时具有优势,因为它根据与其他全局方法难以识别的邻近密集区域的接近程度来识别异常值。

    然而,可解释性是一个问题,因为很难说在什么阈值下数据点可以被视为异常值。

  • DBSCAN 不需要定义多个集群,并且能够检测数据分布任意分布且线性不可分的异常。在处理不同密度的数据传播时,它有其自身的局限性。在我们的案例中,它检测到 16 个数据点作为潜在的异常值。

往期精彩回顾适合初学者入门人工智能的路线及资料下载(图文+视频)机器学习入门系列下载机器学习及深度学习笔记等资料打印《统计学习方法》的代码复现专辑机器学习交流qq群955171419,加入微信群请扫码

【机器学习】使用 IQR、Z 分数、LOF 和 DBSCAN 检测异常值相关推荐

  1. Python数据分析:异常值检验的两种方法 -- Z 分数 上下分位点(放入自写库,一行代码快速实现)

    本文已在公众号 " 数据分析与商业实践 " 首发.关注一下~,更多商业数据分析案例源码等你来撩.后台回复 "异常值" ,即可获取本文的案例示范与包含详细注释的源 ...

  2. 统计学(一): Z 分数 正态分布 (附 Python 实现代码) --Z 检验先修; Z 分数与正态分布两者关系; Z 分数与百分位数的异同;面试要点(以心理学实验为舟)

    背景介绍   笔者的第一本心理学启蒙教材<西奥蒂尼社会心理学>:揭开了自我.环境.群体之间看不见的影响力." 行为背后的目的到底是什么?" " 目的背后的人和 ...

  3. 如何计算 R 语言中的 Z 分数

    在统计学中, z 分数 告诉我们一个值与平均值相差多少标准差.我们使用以下公式来计算 z 分数: z = (X - μ) / σ X 是单个原始数据值 μ 是总体平均值 σ 是总体标准差 本教程解释了 ...

  4. R计算Z分数(Z-Scores)

    R计算Z分数(Z-Scores) 目录 R计算Z分数(Z-Scores) 求单个向量的Z-分数 dataframe单个列的Z分数

  5. z分数(z-score)——之前世今生

    z分数(z-score):也叫标准分数(standard score),是一个分数与平均数的差再除以标准差的过程. 公式: z=(x-μ)/σ.其中x为某一具体分数, μ为平均数,σ为标准差. Z值的 ...

  6. 比较两组数据的差异用什么图更直观_标准差、Z分数到底是什么鬼??标准差与Z分数的原理与实例介绍 | 心理统计学...

    阿猫同志目前在职读研的专业是应用心理学,2月完成了心理与教育测量学的学习,3月目前在自学心理与教育统计学,每日上班+学习的充实生活,让我想说一句 心理测量学需要有心理统计学基础,当时阿猫在学习常模参照 ...

  7. R语言使用scale函数将向量数据或者dataframe指定数据列转换为Z分数(z-Scores、转化为规范化数据)

    R语言使用scale函数将向量数据或者dataframe指定数据列转换为Z分数(z-Scores.转化为规范化数据) 目录

  8. day_3:z分数、正态分布和概率

    z分数 又正负符号和数值两个部分组成,正号表示分数比均值大,负号表示比均值小,数值表示的是原始分数和均值之间差几个标准差 注:z=(原始分数-算术平均数)/标准差 z分数和标准分布 z分数的另一用途是 ...

  9. R使用Z分数和四分位数区间法去除异常值(outlier)

    R使用Z分数和四分位数区间法去除异常值(outlier) 目录 R使用正太分布法和分位数法去除异常值(outlier) 四分位数范围(箱图ÿ

  10. 利用SPSS箱线图与Z分数法判别异常值的比较

    箱线图前提不要求正态分布,而Z分数法前提要求正态分布. 箱线图(Boxplot)也称箱须图(Box-whisker Plot),是利用数据中的五个统计量:最小值.第一四分位数.中位数.第三四分位数与最 ...

最新文章

  1. 新材料,比钢硬一倍,但重量只有钢1/6
  2. error C2664: 'MessageBoxW' : cannot convert parameter 2 from 'const char [2]' to 'LPCWSTR'
  3. python中api是指什么_python中API接口是什么
  4. 使用Android SDK Manager下载sdk时总是出现中断异常的解决办法。
  5. java网络io_彻底搞懂Java的网络IO
  6. MySQL运行一段时间后自动停止问题的排查
  7. mysql字段命名_Mysql 01—数据库表字段的命名规则
  8. Spring Boot + Vue + Shiro 实现前后端分离,写得太好了!
  9. eclipse主题彻底美化——你还在用白底黑字的编辑器吗?
  10. 一、Jquery入门(超详)
  11. 数据结构视频教程 严蔚敏
  12. MapABC地图API
  13. marlin固件函数解析
  14. Excel函数 - Round函数使用方法
  15. 如何在PS(Adobe Photoshop)安装Portraiture3插件教程
  16. Unity接入心知天气,获取当前城市天气状况
  17. 串口拓展测试方法及步骤--信而泰TeleATT测试软件实操
  18. VUE根据url下载文件
  19. html新增和删除行,html5页面结构的变化以及增加和删除标签的总结
  20. LeetCode 1310 子数组异或查询

热门文章

  1. echarts封装 - 续2
  2. Python爬虫之知乎回答
  3. 设置两个路由器连接以扩大WiFi覆盖范围的方法
  4. 随笔---为什么一到选课时教务系统就卡顿甚至登不上去
  5. windows10使用administrator登录后出现“无法使用内置管理员账户打开应用”的解决方法
  6. migration java_如何重置migration
  7. migration php,PHP日记——Lavarel常用语句之Migration篇
  8. Add-Migration
  9. 【智能工厂】智能工厂4.0:数字世界和物理世界的融合
  10. 515. 在每个树行中找最大值(中等 树 广度优先搜索 二叉树)