# 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()
```

### 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()
```

輸出結果是每個資料點所屬的群集類別,以及最終的群心位置。這些資訊可以用於對資料進行聚類分析和可視化。
需要注意的是,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()
```

```
print(kmeans.score(data))
```
* Result: -537.4443398274493
為什麼 Sklearn 套件最後賦予的分數為負,是是因為開發者習慣得到負慣性(negative inertia)的結果,他會累加錯誤標籤的分數,具體是我們一開始並沒有去定義數據上哪些點是正確的類別,所以評估起來就會得到一個很大的負值。這種評估方式是建立在分類器上,並不適合拿來用在聚類分析這種無監督式學習。個人認為聚類分析很難得到量化的結果,只能靠人類的主觀判斷來評估好壞。