1. 程式人生 > >Python之使用K-Means演算法聚類消費行為特徵資料分析(異常點檢測)

Python之使用K-Means演算法聚類消費行為特徵資料分析(異常點檢測)

源資料(這裡僅展示10行):


程式:

#-*- 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 = KMeans(n_clusters = k, max_iter = iteration) 
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()

執行結果: