1、思路
應用Kmeans聚類時,需要首先確定k值,如果k是未知的,需要先確定簇的數量。其方法可以使用拐點法、輪廓系數法(k>=2)、間隔統計量法。若k是已知的,可以直接調用sklearn子模塊cluster中Kmeans方法,對數據進行切割。
另外如若數據集不規則,存在量綱上的差異,也需要對其進行標准化處理。
2、數據的標准化處理
(minmax_scale為sklearn子模塊processing 中 的函數),第一種方法為壓縮變量為mean=0,std=1的無量綱數據,第二種方式會壓縮變量為[0,1]之間無量綱數據 。
3、案例
1)對iris聚類(已知簇類的情況)
情況1,已知k值,k=3
調用KMeans模塊
import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans from pylab import * mpl.rcParams['font.sans-serif'] = ['SimHei'] iris = pd.read_csv(r'iris.csv') # 設置聚為3類,n_clusters =3 X = iris.drop(labels = 'Species',axis = 1) kmeans = KMeans(n_clusters =3 ) kmeans.fit(X) X['cluster'] = kmeans.labels_ X.cluster.value_counts() # 繪制花瓣長度與寬度的散點圖 import seaborn as sns centers = kmeans.cluster_centers_ print(centers) sns.lmplot(x = 'Petal_Length', y= 'Petal_Width', hue = 'cluster', markers = ['^','s','o'], data = X, fit_reg= False, scatter_kws = {'alpha':0.8}, legend_out = False ) plt.scatter(centers[:,2], centers[:,3], marker = '*',color = 'black', s =130) # 繪制簇中心點 plt.xlabel('花瓣長度') plt.ylabel('花瓣寬度') plt.show() iris['Species_map'] = iris.Species.map({'virginica':0,'setosa':1,"versicolor":2}) # 3種類型進行映射到0,1,2 sns.lmplot(x = 'Petal_Length', y= 'Petal_Width', hue = 'Species_map', markers = ['^','s','o'], data = iris, fit_reg= False, scatter_kws = {'alpha':0.8}, legend_out = False ) plt.xlabel('花瓣長度') plt.ylabel('花瓣寬度') plt.show()
生成圖形如下:
對簇中心做雷達圖
import pygal radar_chart = pygal.Radar(fill = True) radar_chart.x_labels = ['花萼長度','花萼寬度', '花瓣長度','花瓣寬度'] # 雷達圖區域繪制 radar_chart.add('C1',centers[0]) radar_chart.add('C2',centers[1]) radar_chart.add('C3',centers[2]) radar_chart.render_to_file('radar_chart.svg')
生成如下圖形,C1類型的花,花萼長和花瓣長都是最大的。C2類型的花,對應的3個指標值都比較小,C3類型的花,3個指標的平均值,恰好落在C1和C2之間。
2)NBA球員數據集聚類(未知k值)
數據集
選定得分、命中率,三分命中率,罰球命中率四個維度進行分析,觀察數據情況,需進行標准化。
- 先對得分和命中率作散點圖,進行觀察
sns.lmplot(x = '得分', y = '命中率', data = players, fit_reg = False, scatter_kws = {'alpha': 0.8,'color': 'steelblue'} ) plt.show()
肉眼無法進行觀察數據集適合分為幾個簇。分別采用 以上確定k值的3種方法進行測試。
拐點法:
from sklearn import preprocessing X = preprocessing.minmax_scale(players[['得分','罰球命中率','命中率','三分命中率']]) # 數據集的標准化 X = pd.DataFrame(X, columns=['得分','罰球命中率','命中率','三分命中率']) k_SSE(X,15)
結果看出,k值在3、4斜率變化比較明顯,在5以后斜率保持一定的水平。所以k取3,4,5均有可能。在比較其他方法。
輪廓系數法及Gap statistic法可視化效果如下:
結合上圖,輪廓系數在大於0的情況下,最大值對應的k值為2,統計量法首次出現正值的k值為3,綜合考慮以上三種方法取k值為3,即將數據集分為3個簇最理想。
- 對得分和命中率進行聚類
kmeans = KMeans(n_clusters = 3) kmeans.fit(X) players['cluster'] = kmeans.labels_ centers = [] for i in players.cluster.unique(): centers.append(players.ix[players.cluster == i, ['得分','罰球命中率','命中率','三分命中率']].mean()) centers = np.array(centers) sns.lmplot(x = '得分', y = '命中率', hue = 'cluster', data = players, markers = ['^','s','o'], fit_reg = False, scatter_kws = {'alpha': 0.8}, legend = False ) plt.scatter(centers[:,0],centers[:,2],c = 'k',marker = '*',s =180) plt.xlabel('得分') plt.ylabel('命中率') plt.show() # 雷達圖繪制 centers_std = kmeans.cluster_centers_ radar_chart = pygal.Radar(fill = True) # 設置填充型雷達圖 radar_chart.x_labels = ['得分','罰球命中率','命中率','三分命中率'] radar_chart.add('C1', centers_std[0]) radar_chart.add('C2', centers_std[1]) radar_chart.add('C3', centers_std[2]) radar_chart.render_to_file('radar_charts.svg')
結果如下圖:
由聚類結果可以發現,三角形區域代表的球員屬於低得分低命中率類型,命中率普遍低於50%,方形區域代表低得分高命中率的球員,圓形區域球員與三角形區域球員具有類似的命中率,單圓形區域球員具有高得分。且該區域存在部分球員具有高得分且高命中率。通過對比雷達圖,C1、C2類球員平均得分差不多,但C2具有更高的命中率。平均罰球命中率和三分球命中率上來看,C1球員也要明顯高於C2.