聚类检测异常点

主要思想:

用聚类方式划分数据为不同的簇,计算簇内每个点对于簇中心的相对距离(相对距离 = 点到簇中心的距离/这个簇所有点到簇中心距离的中位数),可视化后,检测出相对距离较大的点。

注意是每个点到簇中心的距离的中位数,不是平均值,因为异常值对中位数的影响很小,几乎可以忽略,但是对均值的影响很大。

from sklearn import preprocessing
from sklearn.cluster import KMeans
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.style.use('ggplot')


data = pd.read_excel(r'C:\Users\Administrator\Desktop\consumption_data.xls',index_col = 'Id')

data_scale = preprocessing.scale(data)#处理后需要转为dataframe,或者直接手动求均值、方差转换

model = KMeans(n_clusters = 3,max_iter = 500)#分为3类
model.fit(data_scale)

data_scale = pd.DataFrame(data_scale,index = data.index)
data_scale['labels'] = model.labels_

norm = []
for i in range(3):
    norm_tmp = data_scale[['R','F',"M"]][data_scale['labels']==i]-model.cluster_centers_[i]
    norm_tmp = norm_tmp.apply(np.linalg.norm,axis = 1)
    norm.append(norm_tmp/norm_tmp.median())
data_scale.columns = ['R','F','M','labels']

norm = pd.concat(norm)#合并

norm.plot(style = 'ro')#可视化

可见相对距离<2的,为正常点,可以取相对距离的阈值为2

discrete_points = norm[norm>2]
discrete_points.index

>>>
Int64Index([30, 226, 670, 39, 252, 339, 484, 525, 935], dtype='int64', name='Id')

根据阈值删选出异常值,后续可以根据异常值的index删除。

猜你喜欢

转载自blog.csdn.net/weixin_40300458/article/details/81318381
今日推荐