真实数据集的异常值检测简介
此示例介绍了对真实数据集进行鲁棒协方差估计的必须性。它对于异常检测(离群值检测)和更好地理解数据结构都是有用的。
我们从波士顿住房数据集中选择了两组两个变量的数据子集,以说明可以使用几种离群值检测工具进行哪些分析。出于可视化的目的,我们使用的是2维示例,但是应该指出的是,在高维度上事情并非那么简单。
在下面的两个示例来看,主要结论是经验协方差估计(作为一种非稳健的估计)受观测的异构结构的影响很大。尽管鲁棒的协方差估计能够集中于数据分布的主要模式,但它假定数据应该是高斯分布的,从而产生了对数据结构的某种有偏估计,不过在一定程度上还算准确。 One-Class SVM不假设数据分布的任何参数形式,因此可以更好地对数据的复杂形状进行建模。
第一个例子
第一个示例说明了当另外一个簇存在时,鲁棒的协方差估计如何帮助集中在相关簇上。在这里,许多观察结果被混淆为一个,让经验协方差估计效果变差。当然,某些筛选工具能指出存在两个聚类(支持向量机,高斯混合模型,单变量离群值检测……)。但是,如果这是一个高维度的例子,那么所有这些都不容易被应用。
第二个例子
第二个示例显示了最小协方差鲁棒估计器专注于数据分布的主要模式的能力:尽管由于香蕉形分布而难以估算协方差,但位置似乎已得到很好的估计。无论如何,我们可以消除一些较远的离群点。 One-Class SVM能够捕获真实的数据结构,但是困难在于如何调整其核带宽参数,以便在数据散布矩阵的形状和过滤合数据的风险之间取得良好的折衷。
代码实现[Python]
# -*- coding: utf-8 -*-
print(__doc__)
# Author: Virgile Fritsch
# License: BSD 3 clause
import numpy as np
from sklearn.covariance import EllipticEnvelope
from sklearn.svm import OneClassSVM
import matplotlib.pyplot as plt
import matplotlib.font_manager
from sklearn.datasets import load_boston
# 获取数据
X1 = load_boston()['data'][:, [8, 10]] # two clusters
X2 = load_boston()['data'][:, [5, 12]] # "banana"-shaped
# 定义分类器
classifiers = {
"Empirical Covariance": EllipticEnvelope(support_fraction=1.,
contamination=0.261),
"Robust Covariance (Minimum Covariance Determinant)":
EllipticEnvelope(contamination=0.261),
"OCSVM": OneClassSVM(nu=0.261, gamma=0.05)}
colors = ['m', 'g', 'b']
legend1 = {}
legend2 = {}
# 通过几个分类器学习离群点检测的边界
xx1, yy1 = np.meshgrid(np.linspace(-8, 28, 500), np.linspace(3, 40, 500))
xx2, yy2 = np.meshgrid(np.linspace(3, 10, 500), np.linspace(-5, 45, 500))
for i, (clf_name, clf) in enumerate(classifiers.items()):
plt.figure(1)
clf.fit(X1)
Z1 = clf.decision_function(np.c_[xx1.ravel(), yy1.ravel()])
Z1 = Z1.reshape(xx1.shape)
legend1[clf_name] = plt.contour(
xx1, yy1, Z1, levels=[0], linewidths=2, colors=colors[i])
plt.figure(2)
clf.fit(X2)
Z2 = clf.decision_function(np.c_[xx2.ravel(), yy2.ravel()])
Z2 = Z2.reshape(xx2.shape)
legend2[clf_name] = plt.contour(
xx2, yy2, Z2, levels=[0], linewidths=2, colors=colors[i])
legend1_values_list = list(legend1.values())
legend1_keys_list = list(legend1.keys())
# 绘制结果图 (= shape of the data points cloud)
plt.figure(1) # two clusters
plt.title("Outlier detection on a real data set (boston housing)")
plt.scatter(X1[:, 0], X1[:, 1], color='black')
bbox_args = dict(boxstyle="round", fc="0.8")
arrow_args = dict(arrowstyle="->")
plt.annotate("several confounded points", xy=(24, 19),
xycoords="data", textcoords="data",
xytext=(13, 10), bbox=bbox_args, arrowprops=arrow_args)
plt.xlim((xx1.min(), xx1.max()))
plt.ylim((yy1.min(), yy1.max()))
plt.legend((legend1_values_list[0].collections[0],
legend1_values_list[1].collections[0],
legend1_values_list[2].collections[0]),
(legend1_keys_list[0], legend1_keys_list[1], legend1_keys_list[2]),
loc="upper center",
prop=matplotlib.font_manager.FontProperties(size=12))
plt.ylabel("accessibility to radial highways")
plt.xlabel("pupil-teacher ratio by town")
legend2_values_list = list(legend2.values())
legend2_keys_list = list(legend2.keys())
plt.figure(2) # 香蕉形
plt.title("Outlier detection on a real data set (boston housing)")
plt.scatter(X2[:, 0], X2[:, 1], color='black')
plt.xlim((xx2.min(), xx2.max()))
plt.ylim((yy2.min(), yy2.max()))
plt.legend((legend2_values_list[0].collections[0],
legend2_values_list[1].collections[0],
legend2_values_list[2].collections[0]),
(legend2_keys_list[0], legend2_keys_list[1], legend2_keys_list[2]),
loc="upper center",
prop=matplotlib.font_manager.FontProperties(size=12))
plt.ylabel("% lower status of the population")
plt.xlabel("average number of rooms per dwelling")
plt.show()
代码执行
代码运行时间大约:0分3.436秒。
运行代码输出的图片内容如下:
源码下载
- Python版源码文件: plot_outlier_detection_housing.py
- Jupyter Notebook版源码文件: plot_outlier_detection_housing.ipynb