資料分群的目標,是把原本一大群的資料,分成一個個相似的小群體。最簡單的分群演算法,是 k-means clustering,這個演算法的基本步驟大致如下:
- 選出 k 個資料點,做為初始的中心
- 計算每個資料點到這 k 個中心的距離
- 把跟同一個中心最近的資料點視為一群,並以其平均做為新的中心
- 重複步驟 2,直到變化很小或不再變化
我們使用 scikit-learn 的 cluster.KMeans 來幫我們執行 k-means 演算法,使用的資料集是 Wine Data Set,但為了視覺化方便,範例將只使用前兩維特徵。
import matplotlib.pyplot as plt import numpy as np from sklearn.datasets import load_wine from sklearn.cluster import KMeans dataset = load_wine() data = dataset.data[:, :2] print('Data shapes:', data.shape) model = KMeans(n_clusters=3) cluster_labels = model.fit_predict(data) cluster_centers = model.cluster_centers_ plt.subplot(1, 2, 1) plt.plot(data[:, 0], data[:, 1], '.') plt.subplot(1, 2, 2) for clab in set(cluster_labels): idx = np.where(cluster_labels == clab)[0] plt.plot(data[idx, 0], data[idx, 1], '.') plt.plot(model.cluster_centers_[clab, 0], model.cluster_centers_[clab, 1], 'r.', markersize=10) plt.show()在上述範例中,我們事先設定把資料分成三群,並且將分群結果和每一群的中心點畫出來。若需要做更細節的控制,例如如何選擇初始點,以及演算法步驟要重複幾次等,請參考官方文件
如何選擇群體數目,是一個非常重要的問題。其中一種決定方式是,藉由每個點到各自中心的距離總和來評估,雖然這個總和會隨著群體數目變多而減少(數學上是可以證明的,但這裡空間太小了我寫不下不是本教材的關注點所以略過),但我們通常可以選擇變化突然趨緩的地方,作為群體數目即可。下面範例會畫出群體數目分別為 1 到 10 時的距離總和,以及斜率的變化比率:
import matplotlib.pyplot as plt import numpy as np from sklearn.datasets import load_wine from sklearn.cluster import KMeans dataset = load_wine() data = dataset.data[:, :2] print('Data shapes:', data.shape) dist_sum_all = [] for n in range(1, 11): model = KMeans(n_clusters=n) model.fit(data) dist_sum_all.append(model.inertia_) dist_sum_all = np.array(dist_sum_all) slope_change_ratio = np.diff(dist_sum_all[:-1]) / np.diff(dist_sum_all[1:]) fig, ax1 = plt.subplots() ax2 = ax1.twinx() ax1.plot(np.arange(1, 11), dist_sum_all, 'b.-', label='Total distance') ax2.plot(np.arange(2, 10), slope_change_ratio, 'r.-', label='Slope change ratio') ax1.legend(loc='upper center') ax2.legend(loc='upper right') plt.show()資料分群還有許多演算法,例如以階層式的方式來進行分群等等,在此處就暫不介紹。