# Machine Learning Homework 6 K-means Department : Forsetry Student : M10912004 Name : De-Kai Kao (高得愷) ## Introduction K-means(K均值)是一種常用的無監督機器學習演算法,用於對資料進行聚類分析。其目標是將資料分成k個不同的類別,使得每個資料點都被分類至離其最近的類別。 ## Python ### Import ``` import numpy as np import matplotlib.pyplot as plt ``` ### Random data ``` np.random.seed(0) n_samples = 200 data = np.concatenate(( np.random.randn(n_samples, 2) * 0.75 + np.array([2, 2]), np.random.randn(n_samples, 2) * 0.75 + np.array([-2, 2]), np.random.randn(n_samples, 2) * 0.75 + np.array([-1, -1]) )) # 繪製 600 個隨數據樣點 plt.scatter(data[:, 0], data[:, 1], c=labels) plt.title('K-means Clustering') plt.xlabel('X') plt.ylabel('Y') plt.show() ``` ![](https://hackmd.io/_uploads/HJvvNDPI3.png) ### K-means ``` # 選擇分群 num_clusters = 4 # 迭代次數 num_iterations=50 # 隨機選擇初始點 centroids = data[np.random.choice(range(len(data)), num_clusters, replace=False)] plt.title('K-means Clustering') plt.xlabel('X') plt.ylabel('Y') for _ in range(num_iterations): distances = np.linalg.norm(data[:, np.newaxis] - centroids, axis=2) # 每個點到K點的距離 labels = np.argmin(distances, axis=1) # 每點距離最近的K點 for i in range(num_clusters): centroids[i] = np.mean(data[labels == i], axis=0) #print(centroids[i]) if i == 0: plt.plot(centroids[i][0], centroids[i][1], marker="x", markersize=5, color="red") elif i == 1: plt.plot(centroids[i][0], centroids[i][1], marker="x", markersize=5, color="red") elif i == 2: plt.plot(centroids[i][0], centroids[i][1], marker="x", markersize=5, color="red") elif i == 3: plt.plot(centroids[i][0], centroids[i][1], marker="x", markersize=5, color="red") plt.scatter(data[:, 0], data[:, 1], c=labels, alpha=0.5) plt.show() ``` ![](https://hackmd.io/_uploads/rJBdEPwL3.png) 輸出結果是每個資料點所屬的群集類別,以及最終的群心位置。這些資訊可以用於對資料進行聚類分析和可視化。 需要注意的是,K-means演算法對於初始的群心的選擇比較敏感,初始選擇的不同會導致不同的聚類結果。因此,通常會多次運行K-means演算法,選擇產生最優結果的運行。 總結來說,K-means是一種常用的聚類演算法,可以將資料點劃分成k個不同的群集,每個群集具有相似的特徵。通過迭代的方式,K-means演算法將資料點分配到最近的群心所在的類別,並更新群心的位置,直到達到停止條件,停止條件通常是設置使迭代次數,或是直到群心不再移動為止。 ### Sklearn ``` from sklearn.cluster import KMeans # 選擇分群 num_clusters = 4 # 將 K-means 模型擬合到數據 kmeans = KMeans(n_clusters=num_clusters) kmeans.fit(data) # 預測數據所對應的標籤 labels = kmeans.predict(data) # 取得最終群心 centroids = kmeans.cluster_centers_ # 繪製 plt.scatter(data[:, 0], data[:, 1], c=labels, cmap='viridis', alpha=0.5) plt.scatter(centroids[:, 0], centroids[:, 1], marker='x', color='red', s=200) plt.xlabel('X') plt.ylabel('Y') plt.title('K-means Clustering') plt.show() ``` ![](https://hackmd.io/_uploads/rJv_vsFU2.png) ``` print(kmeans.score(data)) ``` * Result: -537.4443398274493 為什麼 Sklearn 套件最後賦予的分數為負,是是因為開發者習慣得到負慣性(negative inertia)的結果,他會累加錯誤標籤的分數,具體是我們一開始並沒有去定義數據上哪些點是正確的類別,所以評估起來就會得到一個很大的負值。這種評估方式是建立在分類器上,並不適合拿來用在聚類分析這種無監督式學習。個人認為聚類分析很難得到量化的結果,只能靠人類的主觀判斷來評估好壞。