离群点检测
离群点成因:数据来源于不同的类、自然变异、数据测量、收集误差
离群点分类:
分类标准 | 分类名称 |
从数据范围 | 全局离群点和局部离群点 |
从数据类型 | 数值型离群点和分类型离群点 |
从属性个数 | 一维离群点和多维离群点 |
离群点检测方法
离群点检测方法 | 方法描述 | 方法评估 |
基于统计 | 大部分基于统计的离群点检测方法是:构建一个概率分布模型,并计算对象符合该模型的概率,将具有低概率的对象视为离群点 | 前提是:知道数据服从何种分布,对高维数据,检验效果很差 |
基于邻近度 | 通常可在数据对象间定义邻近性度量,把远离大部分点的对象视为离群点 | 二维、三维的数据可做散点图观察,大数据不适用,对参数选择敏感,具有全局阙值,不能处理具有不同密度区域的数据集 |
基于密度 | 考虑数据集可能存在不同密度区域,离群点是在低密度区域中的对象 | 给出对象是离群点的定量度量,即使数据具有不同的区域很好处理,大数据集不适用,参数选择比较难 |
基于聚类 | 一种利用聚类检测离群点的方法是:丢弃远离其他簇的小簇。首先聚类所有对象,然后评估对象属于簇的程度 | 基于聚类技术来发现离群点可能死高度有效的,聚类算法产生的簇的质量对该算法产生的离群点的质量影响非常大 |
基于模型的离群点检测方法
基于聚类的离群点检测方法
(1)丢弃远离其他簇的小簇,该过程可简化为丢弃小于某个最小阙值的所有簇。
(2)基于原型的聚类,该过程首先聚类所有对象,然后评估对象属于簇的程度,可用对象到它的簇中心的距离来度量属于簇的程度。
对于基于原型的聚类,有两种方法评估对象属于簇的程度(离群点得分)
a:度量对象到簇原型的距离,并用它作为该对象的离群点得分
b:考虑到簇具有不同的密度,可以度量簇到原型的相对距离,相对距离是点到质心的距离与簇中所有点到质心的距离的中位数之比。
#-*- coding: utf-8 -*-
#使用K-Means算法聚类消费行为特征数据
import numpy as np
import pandas as pd
#参数初始化
inputfile = '../data/consumption_data.xls' #销量及其他属性数据
k = 3 #聚类的类别
threshold = 2 #离散点阈值
iteration = 500 #聚类最大循环次数
data = pd.read_excel(inputfile, index_col = 'Id') #读取数据
data_zs = 1.0*(data - data.mean())/data.std() #数据标准化
from sklearn.cluster import KMeans
model = KMeans(n_clusters = k, n_jobs = 4, max_iter = iteration) #分为k类,并发数4
model.fit(data_zs) #开始聚类
#标准化数据及其类别
r = pd.concat([data_zs, pd.Series(model.labels_, index = data.index)], axis = 1) #每个样本对应的类别
r.columns = list(data.columns) + [u'聚类类别'] #重命名表头
norm = []
for i in range(k): #逐一处理
norm_tmp = r[['R', 'F', 'M']][r[u'聚类类别'] == i]-model.cluster_centers_[i]
norm_tmp = norm_tmp.apply(np.linalg.norm, axis = 1) #求出绝对距离
norm.append(norm_tmp/norm_tmp.median()) #求相对距离并添加
norm = pd.concat(norm) #合并
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号
norm[norm <= threshold].plot(style = 'go') #正常点
discrete_points = norm[norm > threshold] #离群点
discrete_points.plot(style = 'ro')
for i in range(len(discrete_points)): #离群点做标记
id = discrete_points.index[i]
n = discrete_points.iloc[i]
plt.annotate('(%s, %0.2f)'%(id, n), xy = (id, n), xytext = (id, n))
plt.xlabel(u'编号')
plt.ylabel(u'相对距离')
plt.show()