异常值检验的一些方法

Posted Icy Hunter

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异常值检验的一些方法相关的知识,希望对你有一定的参考价值。

异常值检验的一些方法

1.局部离群因子检测(LOF)

LOF算法对数据分布假设没什么要求,能够量化每个数据点的异常程度,是一种基于密度的检测异常值的方法。LOF算法认为非离群点对象周围的密度与其邻域周围的密度类似,而离群点对象周围的密度显著不同于其邻域周围的密度。其核心思想就是看局部的密度与周围的密度相比较,如果局部密度相对稀疏,则可认为是离群值,即异常值。
具体可以参考一文读懂异常检测 LOF 算法(Python代码)讲的还是比较清楚的。

调用sklearn可以较快的实现:

from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn.neighbors import LocalOutlierFactor
from sklearn.decomposition import PCA
# 导入鸢尾花的数据集
iris = datasets.load_iris()
# PCA降维至2维
X = PCA(n_components=2).fit_transform(iris.data)
# 定义一个LOF模型,contamination能够自己定义异常比例,默认自动选取
model = LocalOutlierFactor(n_neighbors=10)
# 训练模型
model.fit(X)
# 预测模型
# 这里是训练数据中就包含着异常值的话,那么适用训练时novelty默认为False,给训练数据打标签使用fit_predict(x)
y = model.fit_predict(X)  # 若样本点正常,返回1,不正常,返回-1

# 可视化预测结果
plt.scatter(X[:, 0], X[:, 1], c=y)  # 样本点的颜色由y值决定
plt.show()

黑色的点即为检测出的异常值。

2.MADe法

from sklearn import datasets
import pandas as pd
import numpy as np
iris = datasets.load_iris()
X = iris.data[:, 0]  # 换成需要检测的一维数据即可
X = pd.DataFrame(X)
col = 0  # 需要检验的dataframe的列
M = X[col].median()
MAD = (np.abs(X[col] - X[col].median())).median()
down = M - 3 * MAD * 1.483
up = M + 3 * MAD * 1.483
error = X[(X[col] < down) | (X[col] > up)]
print(down)
print(up)
if len(error) == 0:
    print("此方法未检测出异常值")
else:
    print(error)

运行结果

3.修正的Z得分法

from sklearn import datasets
import pandas as pd
import numpy as np
iris = datasets.load_iris()
X = iris.data[:, 0]  # 换成需要检测的一维数据即可
X = pd.DataFrame(X)
col = 0
MAD = (np.abs(X[col] - X[col].median())).median()
M = np.abs(0.6745 * (X[col] - X[col].median()) / MAD)
if len(M[M > 3.5]) == 0:
    print("检测无异常值")
else:
    print(M[M > 3.5])


说明此方法在此数据中没有检测出异常值

4.boxplot法


import numpy as np
from statsmodels.stats.stattools import medcouple
import pandas as pd
np.random.seed(0)
data = np.random.rand(10000)
data[0] = data[0] * 3
data = pd.DataFrame(data)
col = 0  # 所选需要检验的dataframe的列
des = data[col].describe()

Q1 = des.loc["25%"]
Q3 = des.loc["75%"]
IQR = Q3 - Q1

I_L = Q1 - 1.5 * IQR
I_U = Q3 + 1.5 * IQR

O_L = Q1 - 3 * IQR
O_U = Q3 + 3 * IQR

error = data[(data[col] < O_L) | (data[col] > O_U)]
error_may = data[((data[col] > O_L) & (data[col] < I_L)) | ((data[col] < O_U) & (data[col] > I_U))]
if len(error) == 0 and len(error_may) == 0:
    print("未检测出异常值")
if len(error_may) != 0:
    print("可能为异常值:")
    print(error_may)
if len(error) != 0:
    print("检测出异常值为")
    print(error)



结果

5.修正的boxplot法

import numpy as np
from statsmodels.stats.stattools import medcouple
import pandas as pd
np.random.seed(0)
data = np.random.rand(10000)
data[0] = data[0] * 3

data = pd.DataFrame(data)
col = 0
if len(data[col]) > 10000:  # 大于10000就抽样计算估计数据的MC
    samples = data[col].sample(n=10000)
else:
    samples = data[col]

MC = medcouple(samples)
des = data[col].describe()

Q1 = des.loc["25%"]
Q3 = des.loc["75%"]
IQR = Q3 - Q1

L = 0
U = 0
if MC >= 0:
    L = Q1 - 1.5 * np.exp(-3.5 * MC) * IQR
    U = Q3 + 1.5 * np.exp(4 * MC) * IQR
else:
    L = Q1 - 1.5 * np.exp(-4 * MC) * IQR
    U = Q3 + 1.5 * np.exp(3.5 * MC) * IQR

print(L)
print(U)

error = data[(data[col] < L) | (data[col] > U)]
if len(error) == 0:
    print("未检测出异常值")
else:
    print("检测出的异常值为")
    print(error)

结果

以上是关于异常值检验的一些方法的主要内容,如果未能解决你的问题,请参考以下文章

R语言︱异常值检验离群点分析异常值处理

R语言使用car包的outlierTest函数通过假设检验的方法检测回归模型中的异常值(outlier)输出异常值对应的统计量p值以及Bonferonnii校正p值

R语言︱异常值检验离群点分析异常值处理

异常检测方法 二

对于异常值的检测

R语言︱异常值检验离群点分析异常值处理