# 機器學習 06:無監督式學習-KMeans、DBSCAN
###### tags: `ML model`, `Unsupervised Learning`, `KMeans`, `DBSCAN`
## K-means
1. 先決定要分為 k 群
2. 將每一個點分到離自己最近的一個質心
3. 重新計算並最小化歐式距離調整質心位置
```python=
from sklearn.cluster import KMeans
k = 5
kmeans = KMeans(n_clusters=k)
y_pred = kmeans.fit_predict(X)
# 找質心
kmeans.cluster_centers_
```
若資料團的直徑差異很大,則在 K-means 的表現會較差,因為此演算法只在乎質心離資料點的距離。
- 硬分類
將各資料點分到單一群體。
- 軟分類
將各資料點指定它屬於各群體的分數,此分數可以是距離、相似度或高斯函數等。
```python=
# 該點到質心的距離矩陣
kmeans.transform(X_new)
```
<font color="#f00">**同時可用這個技巧對資料做轉換,是個非常高效的非線性降維法。**</font>
<br>
### 選擇初始質心的方法
1. 指定質心位置
設定質心的位置,並將 n_init 設為 1。
```python=
good_init = np.array([[-3, 3], [-3, 2], [-1, 2], [0, 2]])
kmeans = KMeans(n_clusters=5, init=good_init, n_init=1)
```
2. 使用隨機初始值執行多次
KMeans 會執行演算法 n_init 次,並保留 intertia(各資料點和距離最近的質心均方距離)最低的模型。
3. KMeans++
初始質心間的距離越遠越好,可大幅減少演算法尋找最佳解的次數,也可以防止演算法收斂至次佳解。
<br>
### KMeans 的限制
必須執行演算法多次來避免得到次佳解,此外如果群聚大小不一致、有不同的密度、或不是球形時,KMeans 表現不會太好。

<br>
### 用分群來做圖像分割
圖像分割是將一張圖分成多個子圖,此處為顏色分割,單純將顏色相近的像素分到同一個子圖,實際的應用如:計算某個區域森林總面積。

```python=
X = image.reshape(-1, 3)
kmeans = KMeans(n_clusters=8, random_state=42).fit(X) # 8色
segmented_img = kmeans.cluster_centers_[kmeans.labels_] # 將點換成質心顏色
segmented_img = segmented_img.reshape(image.shape)
```

由於瓢蟲的紅色站很小比例,所以在 8 色以下會被納入其餘的部分。
---
## DBSCAN
1. 幫每一個資料點計算有多少資料點離它一小段距離 $ε$ 內,該區域稱為該資料點的 $ε$ 近鄰。
2. 如果某個資料點有至少 min_samples 個資料點在它的 $ε$ 近鄰之內(包括自己),就將它視為核資料點(core instance)。
3. 在核資料點近鄰的所有資料點或核資料點都將組成一個群體。
4. 如果某個資料點不是和資料點,而且近鄰沒有核資料點,就將它視為異常資料點。
```python=
from sklearn.cluster import DBSCAN
from sklearn.datasets import make_moons
X, y = make_moons(n_samples=1000, noise=0.05)
dbscan = DBSCAN(eps=0.05, min_samples=5)
dbscan.fit(X)
# 取得所有資料點的標籤,標籤是 -1 的代表異常資料點
dbscan.labels_
# 資料點變數取得核資料點的索引,len()代表有幾個核資料點
len(dbscan.core_sample_indices_)
# 核資料點位置
dbscan.components_
```
