1.什么是K-Means?
K均值算法聚類
關鍵詞:K個種子,均值
聚類的概念:一種無監督的學習,事先不知道類別,自動將相似的對象歸到同一個簇中
K-Means算法是一種聚類分析(cluster analysis)的算法,其主要是來計算數據聚集的算法,主要通過不斷地取離種子點最近均值的算法.
K-Means算法的思想很簡單,對於給定的樣本集,按照樣本之間的距離大小,將樣本集划分為K個簇。讓簇內的點盡量緊密的連在一起,而讓簇間的距離盡量的大.
2.k-Means原理
每次計算距離采用的是歐式距離
步驟圖:
步驟總結:
- 從數據中選擇k個對象作為初始聚類中心;
- 計算每個聚類對象到聚類中心的距離來划分;
- 再次計算每個聚類中心
- 2~3步for循環,直到達到最大迭代次數,則停止,否則,繼續操作。
- 確定最優的聚類中心
主要優點:
- 原理比較簡單,實現也是很容易,收斂速度快。
- 聚類效果較優。
- 算法的可解釋度比較強。
- 主要需要調參的參數僅僅是簇數k。
- 當簇近似為高斯分布時,效果是最高的.
- 對處理大數據集該算法保持可伸縮性和高效率
主要缺點:
-
K-Means算法需要用初始隨機種子點來搞,這個隨機種子點太重要,不同的隨機種子點會有得到完全不同的結果。(K-Means++算法可以用來解決這個問題,其可以有效地選擇初始點)
- 必須事先給出k(要生成的簇的數目),而且對初值敏感,對於不同的初值,可能會導致不同的結果.
- 對於不是凸的數據集比較難收斂
- 如果各隱含類別的數據不平衡,比如各隱含類別的數據量嚴重失衡,或者各隱含類別的方差不同,則聚類效果不佳。
- 采用迭代方法,得到的結果只是局部最優。
- 對噪音和異常點比較的敏感。
3.K-Means算法應用:
- 對於多維數據的分類,效果很好
- 二維坐標點的X,Y 坐標,其實是一種向量,是一種數學抽象。現實世界中很多屬性是可以抽象成向量的,比如,我們的年齡,我們的喜好,我們的商品,等等,能抽象成向量的目的就是可以讓計算機知道某兩個屬性間的距離。如:我們認為,18歲的人離24歲的人的距離要比離12歲的距離要近,鞋子這個商品離衣服這個商品的距離要比電腦要近,等等。解決實際問題比較好
4.K-Means實例-亞洲國家隊足球水平分類
1 import numpy as np 2 3 import pandas as pd 4 5 # cluster :簇,一堆 6 # 只有分類 7 from sklearn.cluster import KMeans 8 9 import matplotlib.pyplot as plt 10 %matplotlib inline 11 12 from mpl_toolkits.mplot3d.axes3d import Axes3D 13 import warnings 14 warnings.filterwarnings('ignore') 15 16 # 2006年世界杯,2010年世界杯,2007亞洲杯,比賽數據 17 football = pd.read_csv('./AsiaFootball.txt') 18 19 X = football.iloc[:,1:] 20 21 kmeans = KMeans(n_clusters=5) 22 23 # 無監督學習 PCA也是無監督 NMF無監督 24 kmeans.fit(X) 25 y_ = kmeans.predict(X) 26 27 # 分成3類 28 for i in range(3): 29 index = np.argwhere(y_ == i).reshape(-1) 30 print('類別是%d國家隊有:'%(i),football['國家'].loc[index].get_values()) 31 32 # 分成5類 33 for i in range(5): 34 index = np.argwhere(y_ == i).reshape(-1) 35 print('類別是%d國家隊有:'%(i),football['國家'].loc[index].get_values())
加載的數據結構:
分成3類打印輸出:
分成5類打印輸出:
分類好了,但是我們不知道分成4類好還是分成5類好,現在選取一些指標來評判一下:
(1)輪廓系數 Silhouette Coefficient
1 # 輪廓系數 2 from sklearn.metrics import silhouette_score 3 4 for i in range(2,16): 5 kmeans = KMeans(n_clusters=i) 6 kmeans.fit(X) 7 y_ = kmeans.predict(X) 8 s = silhouette_score(X,y_) 9 print('聚類個數是:%d。輪廓系數是:%0.2f'%(i,s))
由輪廓系數分析可知,當分為6類的時候,效果最好
(2)calinski_harabasz_score CH分數(值越大,效果越好)
1 for i in range(2,16): 2 kmeans = KMeans(n_clusters=i) 3 kmeans.fit(X) 4 y_ = kmeans.predict(X) 5 s = metrics.calinski_harabasz_score(X,y_) 6 print('聚類個數是:%d。calinski_harabasz_score:%0.2f'%(i,s))
(3)davies_bouldin_score 戴維森堡丁指數DBI(度量是每個聚類最大相似度的均值)
1 for i in range(2,16): 2 kmeans = KMeans(n_clusters=i) 3 kmeans.fit(X) 4 y_ = kmeans.predict(X) 5 s = metrics.davies_bouldin_score(X,y_) 6 print('聚類個數是:%d。davies_bouldin_score:%0.2f'%(i,s))
以上三種方式得到的最優分類均不同,這是因為數據的原因,數據不太好.
5.Kmeans評價指標,這個就是聚類的衡量指標,之后再具體詳細的解釋一下
(1)輪廓系數 metrics.silhouette_score
(2)蘭德系數 metrics.adjusted_rand_score
(3)互信息指標 metrics.adjusted_mutual_info_score
(4)同質性 homogeneity_completeness_v_measure
(5)Calinski-Harabasz索引 metrics.calinski_harabasz_score
(6)Davies-Bouldin索引 metrics.davies_bouldin_score
補充:
1.k-Means算法,初值的選擇,對聚類結果有影響嗎?
k-Means是初值敏感的,舉個例子:
對於左圖來說,使用k-means分類,我們肉眼可見,選擇初值會在四個區域選擇四個樣本,
但是如圖所示,在第二部分選擇了兩個樣本作為初始值,而第一部分沒有選擇,
這種情況下,最終的分類結果可能是右圖所示,這樣的話結果就不太好,分類效果明顯不好,
所以,由此可見,初值的選擇對分類有很大的影響.
我覺得有一種解決方法是:
k-means++算法:
先隨機選擇一個樣本點為初始值,然后計算其他所有樣本到該該本點的距離,然后計算加權平均,相當於給每個樣本點一個權值,也就是被選中的概率,然后按照概率選擇其他的初始值,並不是概率高的一定會被選中,概率低的也可能會被選中,這是一個概率問題,一般來說選中都是距離第一個初始值比較遠的,這樣我們就有下一個聚類中心了,再然后找第三個聚類中心的話,更新一下之前的距離權值,根據樣本到兩個聚類中心的距離,哪個距離大選擇哪個,這樣再根據概率挑選出第三個聚類中心,之后的步驟是一樣的,這就是k-means++算法
2.k-means使用場景
k-means其實對樣本的分布是有要求的,我們認為k個樣本其實是服從高斯混合分布的,並且每個高斯分布的方差是一樣的,其實也就是每個簇的方差是一樣的.
3.k-means的公式化解釋:
我們上邊所說的原理其實就是兩個公式的重復循環
4.如果樣本量巨大的話,可以考慮使用mini-batch k-means算法
5.k-means算法可能會振盪
采用迭代的方法,多做幾次,每次結果可能都不一樣,具體哪個效果好,可能需要人為去判斷.