【算法6】K-Means聚類

    聚類屬於無監督分類算法。用得較多的有基於距離的聚類——K-Means,基於密度的聚類——DBSCAN。可以用作數據降維、數據離散壓縮、客戶分羣等用途,這裏直接進入主題:

K-Means

1 K-Means描述
    ⾸先,選擇K個初始質心,其中K是我們指定的參數,即所期望的簇的個數。每個點指派到最近的質心,而指派到⼀一個質心的點集爲⼀一個簇。然後,根據指派到簇的點,更更新每個簇的質心。重複指派和更更新步驟,直到簇不不發⽣生變化,或等價地,直到質⼼不發⽣生變化。K-Means的核⼼心任務就是根據我們設定好的K,找出K個最優的質心,並將離這些質心最近的數據分別分配到這些質心代表的簇中去。具體過程可以總結如下:
    創建k個點作爲初始質⼼心(通常是隨機選擇)
    當任意⼀一個點的簇分配結果發⽣生改變時:
    對數據集中的每個點:
    對每個質⼼心:
    計算質⼼心與數據點之間的距離
    將數據點分配到據其最近的簇
    對每個簇,計算簇中所有點的均值並將均值作爲新的質⼼心
    直到簇不不再發⽣生變化或者達到最⼤大迭代次數
    那什麼情況下,質心的位置會不再變化呢?當我們找到一個質心,在每次迭代中被分配到這個質⼼上的樣本都是一致的,即每次新生成的簇都是一致的,所有的樣本點都不會再從一個簇轉移到另一個簇,質心就不會變化了。

2 K-Means細節
    聚類算法聚出的類有什麼含義呢?這些類有什麼樣的性質?我們認爲, 被分在同⼀一個簇中的數據是有相似性的,而不同簇中的數據是不同的,當聚類完畢之後,我們就要分別去研究每個簇中的樣本都有什麼樣的性質,從而根據業務需求制定不同的商業或者科技策略略。聚類算法的⽬目的就是追求“簇內差異小,簇外差異大”。⽽而這個“差異“,由樣本點到其所在簇的質心的距離來衡量。對於一個簇來說,所有樣本點到質心的距離之和越小,我們就認爲這個簇中的樣本越相似,簇內差異就越小。而距離的衡量方法有多種,令 表示簇中的一個樣本點, 表示該簇中的質心, n表示每個樣本點中的特徵數目, i表示組成點 的每個特徵,則該樣本點到質心的距離可以由以下距離來度量。

3 距離種類

數據距離
    歐幾里得距離:
d(x,u)=[i=1n[xiui]2]1/2 d(x,u)=[\sum_{i=1}^n [x_i-u_i]^2]^{1/2}
    曼哈頓距離:
d(x,u)=i=1n[xiui] d(x,u)=\sum_{i=1}^n [|x_i-u_i|]
    閔可夫斯基距離:
d(x,u)=[i=1n[xiui]n]1/2 d(x,u)=[\sum_{i=1}^n [|x_i-u_i|]^n]^{1/2}     當爲n=1n=1時,就是曼哈頓距離,當爲n=2n=2時即爲歐式距離,當nn趨於⽆無窮時,即爲切⽐比雪夫距離。

文本距離
    餘弦相關係數:
cos(Θ)=i=1n[xiu][i=1n[xi]n]1/2[i=1n[ui]n]1/2 cos(\Theta)=\frac{\sum_{i=1}^n [| x_i*u|]}{[\sum_{i=1}^n [|x_i |]^n]^{1/2}*[\sum_{i=1}^n [| u_i|]^n]^{1/2}}
    傑卡德係數:
J(A,B)=ABAB J(A,B)=\frac{|A\bigcap B|}{|A\bigcup B|}
4 模型優化條件
    在聚類算法中, 組內誤差平⽅方和(SSESSE)是我們判斷模型是否最優的重要指標,我們希望求得的模型是在給定K值得情況下SSESSE最⼩小的模型,即在相同的K值情況下聚類模型SSESSE越⼩小越好,這也是聚類算法最核⼼心的優化條件。
    聚類算法中的目標函數是實現聚類這一目標所使用的函數,如最小化對象到其所屬類的質心距離等,這里需要注意,一般如果採用距離作爲鄰近度衡量標準,則目標函數往往是利用最小距離來構建聚類類別,而若採用相似度作爲鄰近度衡量標準,則⽬標函數就是利⽤用最大化相似度和來構建聚類類別.
    質心是聚類別的原型,一般可用均值或中位數來表示。但無論如何,在一旦確定距離衡量方法或鄰近度函數(如歐式距離等),並在模型優化條件(SSE最小)的指導下,目標函數和質心選取⽅方法都會隨之確定,常⽤用鄰近度函數、質⼼心和目標函數組合如下:
在這裏插入圖片描述
    這一切實際上是建立在嚴格的數學理論推導的基礎之上的,推導方法之一就是利利⽤用梯度下降進行計算。梯度下降是機器學習中最常用的局部最優化方法,我們在迴歸類算法中已經對其進行了詳細的解釋,此處簡單介紹梯度下降在聚類算法中的應⽤用。首先,我們需要定義聚類算法中的符號集:
在這裏插入圖片描述
    那麼:
SSE=i=1kxϵcin[cix]2 SSE=\sum_{i=1}^k \sum_{x\epsilon c_i}^n [|c_i-x|]^2
其中cic_i是第ii個簇,xxcic_i中的點,cic_i是第ii個簇的質心。我們這里驗證最常用的,當採用歐式距離時當且僅當質心爲均值的時候才能夠保證在目標函數的聚類過程中SSESSE保持最小。

5 python—sklearn實現K-Means

from sklearn.datasets import make_blobs
#⾃自⼰己創建數據集
X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=1)
plt.scatter(X[:, 0], X[:, 1]
,marker='o' #點的形狀
,s=8 #點的⼤大⼩小
);
#如果我們想要看⻅見這個點的分佈,怎麼辦?
color = ["red","pink","orange","gray"]
for i in range(4):
plt.scatter(X[y==i, 0], X[y==i, 1]
,marker='o' #點的形狀
,s=8 #點的⼤大⼩小
,c=color[i]
)

from sklearn.cluster import KMeans
n_clusters = 3
cluster = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
#重要屬性labels_,查看聚好的類別,每個樣本所對應的類
y_pred = cluster.labels_
y_pred
#KMeans因爲並不不需要建⽴立模型或者預測結果,因此我們只需要fit就能夠得到聚類結果了了
#KMeans也有接⼝口predict和fit_predict,表示學習數據X並對X的類進⾏行行預測
#但所得到的結果和我們不不調⽤用predict,直接fit之後調⽤用屬性labels⼀一模⼀一樣
pre = cluster.fit_predict(X)
pre == y_pred
#我們什什麼時候需要predict呢?當數據量量太⼤大的時候!
#其實我們不不必使⽤用所有的數據來尋找質⼼心,少量量的數據就可以幫助我們確定質⼼心了了
#當我們數據量量⾮非常⼤大的時候,我們可以使⽤用部分數據來幫助我們確認質⼼心
#剩下的數據的聚類結果,使⽤用predict來調⽤用
cluster_smallsub = KMeans(n_clusters=n_clusters, random_state=0).fit(X[:200])
y_pred_ = cluster_smallsub.predict(X)
y_pred == y_pred_
#但這樣的結果,肯定與直接fit全部數據會不不⼀一致。有時候,當我們不不要求那麼精確,或者我們的數據量量
實在太⼤大,那我們可以使⽤用這樣的⽅方法。
#重要屬性cluster_centers_,查看質⼼心
centroid = cluster.cluster_centers_
centroid
centroid.shape
#重要屬性inertia_,查看總距離平⽅方和
inertia = cluster.inertia_
inertia
color = ["red","pink","orange","gray"]
for i in range(n_clusters):
plt.scatter(X[y_pred==i, 0], X[y_pred==i, 1]
,marker='o' #點的形狀
,s=8 #點的⼤大⼩小
,c=color[i]
)
plt.scatter(centroid[:,0],centroid[:,1]
,marker="x"
,s=15
,c="black");

6 評估指標
聚類沒有標籤,即不知道真實答案的預測算法,我們必須完全依賴評價簇內的稠密程度(簇內差異小)和簇間的離散程度(簇外差異⼤)來評估聚類的效果。其中輪廓係數是最常⽤用的聚類算法的評價指標。它是對每個樣本來定義的,它能夠同時衡量量:
    1)樣本與其自身所在的簇中的其他樣本的相似度a,等於樣本與同一簇中所有其他點之間的平均距離。
    2)樣本與其他簇中的樣本的相似度b,等於樣本與下一個最近的簇中的所有點之間的平均距離。
    根據聚類的要求 ”簇內差異小,簇外差異大,我們希望b永遠大於a,並且大得越多越好
    單個樣本的輪廓係數計算爲:
在這裏插入圖片描述
    這個公式可以被解析爲:
在這裏插入圖片描述
    很容易易理理解輪廓係數範圍是(-1,1),其中值越接近1表示樣本與⾃自己所在的簇中的樣本很相似,並且與其他簇中的樣本不相似,當樣本點與簇外的樣本更相似的時候,輪廓係數就爲負。當輪廓係數爲0時,則代表兩個簇中的樣本相似度一致,兩個簇本應該是一個簇。
    如果一個簇中的大多數樣本具有比較高的輪廓係數,則簇會有較⾼的總輪廓係數,則整個數據集的平均輪廓係數越高,則聚類是合適的。如果許多樣本點具有低輪廓係數甚至負值,則聚類是不合適的,聚類的超參數K可能設定得太大或者太小。

    輪廓係數的python檢驗:

from sklearn.metrics import silhouette_score
from sklearn.metrics import silhouette_samples
X
y_pred
silhouette_score(X,y_pred)
silhouette_score(X,cluster_.labels_)
#觀察⼀一下不不同的K下,輪廓係數發⽣生什什麼變化?
n_clusters = 5
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
silhouette_score(X,cluster_.labels_)
silhouette_samples(X,y_pred)

    輪廓係數有很多優點,它在有限空間中取值,使得我們對模型的聚類效果有一個“參考”。並且,輪廓係數對數據的分佈沒有假設,因此在很多數據集上都表現良好。但它在每個簇的分割比較清洗時表現最好。但輪廓係數也有缺陷,它在凸型的類上表現會虛高,比如基於密度進⾏行行的聚類,或通過DBSCAN獲得的聚類結果,如果使用輪廓係數來衡量,則會表現出比真實聚類效果更高的分數。
    關於K-Means聚類就先寫到這裏,再會。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章