基于LOF算法的异常值检测
LOF算法简介
LOF异常检测算法是一种基于密度的异常检测算法,基于密度的异常检测算法主要思想是:给定的样本数据集,对于数据集中的点,如果其局部领域的点都很密集,那么这个点大概率为正常的数据点;而如果这个点距离其相邻的点距离较远,也就是在一个局部领域的点密度较小,那么这个点可能为异常点。
Sklearn官网LOF算法应用实例1
clf.negative_outlier_factor_
输出:array([ -0.98214286, -1.03703704, -73.36970899, -0.98214286])
绝对值越大于1则越有可能是异常。很明显101.1最有可能是异常。
Sklearn官网LOF算法应用实例2
导入包:
构造二维数据,以及一些离群点,并可视化:
LOF算法:
根据X_scores可视化,红色圈越大,该点越可能是异常点:
基于LOF算法鸢尾花数据集异常值检测
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from sklearn.neighbors import LocalOutlierFactor
from sklearn.datasets import load_iris
matplotlib.rcParams['font.sans-serif']=['SimHei'] # 用黑体显示中文
%matplotlib inline
读取数据
iris_data = load_iris()
iris_data.data[0:5,:]
array([[5.1, 3.5, 1.4, 0.2],
[4.9, 3. , 1.4, 0.2],
[4.7, 3.2, 1.3, 0.2],
[4.6, 3.1, 1.5, 0.2],
[5. , 3.6, 1.4, 0.2]])
# 数据规模
iris_data.data.shape
(150, 4)
# 特征
iris_data.feature_names
['sepal length (cm)',
'sepal width (cm)',
'petal length (cm)',
'petal width (cm)']
# 查看类别
pd.DataFrame(iris_data.target).value_counts(), iris_data.target_names
(0 50
1 50
2 50
dtype: int64,
array(['setosa', 'versicolor', 'virginica'], dtype='<U10'))
构造数据
这里为方便可视化,只选取iris数据集中 ‘sepal width (cm)’ 和 ‘petal width (cm)’ 两个特征
data = iris_data.data[:, [1, 3]]
data = pd.DataFrame(data, columns=iris_data.feature_names[1:4:2])#['sepal width (cm)','petal width (cm)']
data.head()
sepal width (cm) | petal width (cm) | |
---|---|---|
0 | 3.5 | 0.2 |
1 | 3.0 | 0.2 |
2 | 3.2 | 0.2 |
3 | 3.1 | 0.2 |
4 | 3.6 | 0.2 |
可视化,画出可疑异常点
# 可视化两个特征'sepal width (cm)','petal width (cm)'
data.plot(kind="scatter", x="sepal width (cm)", y="petal width (cm)", c='r', figsize=(6,2))
## 圈出可疑的异常点
plt.plot(2.3, 0.3, "ko", markersize=20, markerfacecolor="none")
plt.annotate("可能异常点", xy=(2.3, 0.48), xytext=(2, 0.75), arrowprops=dict(facecolor="blue"))
plt.plot(3.8, 2.1, "ko", markersize=30, markerfacecolor="none")
plt.annotate("可能异常点", xy=(3.9, 1.9), xytext=(4, 1.5), arrowprops=dict(facecolor="blue"))
plt.plot(4.4, 0.4, "ko", markersize=20, markerfacecolor="none")
plt.annotate("可能异常点", xy=(4.3, 0.5), xytext=(4.5, 1), arrowprops=dict(facecolor="blue"))
Text(4.5, 1, '可能异常点')
LOF算法
lof = LocalOutlierFactor(n_neighbors=30, metric="minkowski")
outlier_pre = lof.fit_predict(data.values)
"异常值数量:%d"%np.sum(outlier_pre==-1)
'异常值数量:7'
# 异常点
data[outlier_pre==-1]
sepal width (cm) | petal width (cm) | |
---|---|---|
15 | 4.4 | 0.4 |
33 | 4.2 | 0.2 |
41 | 2.3 | 0.3 |
60 | 2.0 | 1.0 |
109 | 3.6 | 2.5 |
117 | 3.8 | 2.2 |
131 | 3.8 | 2.0 |
scores = lof.negative_outlier_factor_# negative_outlier_factor_数值越大越正常;数值越小越不正常,可能是离群点
scores = (scores.max()-scores)/(scores.max()-scores.min())
data.plot(kind="scatter", x="sepal width (cm)", y="petal width (cm)", c='r', figsize=(6,2))
plt.scatter(data["sepal width (cm)"], data["petal width (cm)" ], s=800*scores, edgecolors='k', facecolor="none",label="score")