機器學習經典算法之k-means聚類

聚類就是將某個數據集中的樣本按照之間的某些區別劃分爲若干個不相交的子集,我們把每個子集稱爲一個“簇”。劃分完成後,每個簇都可能對應着某一個類別;需說明的是,這些概念對聚類算法而言事先是未知的,聚類過程僅能自動形成簇結構,簇對應的概念語義由使用者來把握和命名。

 

有關聚類的算法很多,下面這張表格引用自Scikit-learn 官方文檔,從這張表中可以看到各個聚類算法之間的不同以及對不同數據及劃分時的匹配程度,和優劣性。我們在選擇聚類算法的時候,首先一定要熟悉自己的數據,大概瞭解自己的數據是怎樣的一個分佈和結構。這樣,有利於我們選擇合適的算法,從而得到優秀的聚類結果。這篇文章僅僅介紹K-means聚類算法,以及它的推廣版K-mean++算法。

k-means算法是使用最廣泛的聚類算法之一。聚類的目的是把相似的樣本聚到一起,把不相似的樣本分開。對於給定的樣本集,按照樣本之間的距離大小,將樣本集劃分爲K個簇。讓簇內的點儘量緊密的連在一起,而讓簇間的距離儘量的大。

K-means算法旨在選擇一個質心, 能夠最小化慣性或簇內平方和的標準:

$$\sum{i=0}^{n} \min _{\mu{j} \in C}\left(\left|x{i}-\mu{j}\right|^{2}\right)$$

K-means算法原理分析

k-means算法是聚類分析中使用最廣泛的算法之一。它把n個對象根據它們的屬性分爲k個簇以便使得所獲得的簇滿足:同一簇中的對象相似度較高;而不同簇中的對象相似度較小。 k-means算法的基本過程如下所示:

  1. 首先隨機選取K個初始質心,最基本的方法是從數據集$X$中選擇$K$個樣本。
  2. 將每個樣本分配到其最近的質心。通過取分配給前一個質心的所有樣本的平均值來創建新的質心。
  3. 計算新舊質心之間的差值,算法重複最後兩個步驟,直到該值小於閾值。換句話說,算法重複這個步驟,直到質心不再明顯移動。

下圖是Scikit-learn具體實現代碼:

print(__doc__)
​
# Author: Phil Roth <[email protected]>
# License: BSD 3 clause
​
import numpy as np
import matplotlib.pyplot as plt
​
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
​
plt.figure(figsize=(12, 12))
​
n_samples = 1500
random_state = 170
X, y = make_blobs(n_samples=n_samples, random_state=random_state)
​
# Incorrect number of clusters
y_pred = KMeans(n_clusters=2, random_state=random_state).fit_predict(X)
​
plt.subplot(221)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.title("Incorrect Number of Blobs")
​
# Anisotropicly distributed data
transformation = [[0.60834549, -0.63667341], [-0.40887718, 0.85253229]]
X_aniso = np.dot(X, transformation)
y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_aniso)
​
plt.subplot(222)
plt.scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred)
plt.title("Anisotropicly Distributed Blobs")
​
# Different variance
X_varied, y_varied = make_blobs(n_samples=n_samples,
                                cluster_std=[1.0, 2.5, 0.5],
                                random_state=random_state)
y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_varied)
​
plt.subplot(223)
plt.scatter(X_varied[:, 0], X_varied[:, 1], c=y_pred)
plt.title("Unequal Variance")
​
# Unevenly sized blobs
X_filtered = np.vstack((X[y == 0][:500], X[y == 1][:100], X[y == 2][:10]))
y_pred = KMeans(n_clusters=3,
                random_state=random_state).fit_predict(X_filtered)
​
plt.subplot(224)
plt.scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_pred)
plt.title("Unevenly Sized Blobs")
​
plt.show()

K-means算法的優缺點

優點:簡單,易於理解和實現;收斂快,一般僅需5-10次迭代即可,高效

缺點:

  • 對K值得選取把握不同對結果有很大的不同(初始化不同質心的計算通常會進行幾次。幫助解決這個問題的一種方法是 k-means++ 初始化方案,它已經在 scikit-learn 中實現(使用 init='k-means++' 參數)。 這將初始化質心(通常)彼此遠離,相對隨機初始化得到更好的結果)
  • 對於初始點的選取敏感,不同的隨機初始點得到的聚類結果可能完全不同
  • 對於不是凸的數據集比較難收斂
  • 對噪點過於敏感,因爲算法是根據基於均值的
  • 結果不一定是全局最優,只能保證局部最優
  • 對球形簇的分組效果較好,對非球型簇、不同尺寸、不同密度的簇分組效果不好。

K-means算法的優缺點

優點:簡單,易於理解和實現;收斂快,一般僅需5-10次迭代即可,高效

缺點:

  • 對K值得選取把握不同對結果有很大的不同(初始化不同質心的計算通常會進行幾次。幫助解決這個問題的一種方法是 k-means++ 初始化方案,它已經在 scikit-learn 中實現(使用 init='k-means++' 參數)。 這將初始化質心(通常)彼此遠離,相對隨機初始化得到更好的結果)
  • 對於初始點的選取敏感,不同的隨機初始點得到的聚類結果可能完全不同
  • 對於不是凸的數據集比較難收斂
  • 對噪點過於敏感,因爲算法是根據基於均值的
  • 結果不一定是全局最優,只能保證局部最優
  • 對球形簇的分組效果較好,對非球型簇、不同尺寸、不同密度的簇分組效果不好。

(1)獲取更多優質內容及精彩資訊,可前往:https://www.cda.cn/?seo

(2)瞭解更多數據領域的優質課程:

 

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