# EX 10:\_K-means群聚法

[https://scikit-learn.org/stable/auto\_examples/cluster/plot\_cluster\_iris.html#sphx-glr-auto-examples-cluster-plot-cluster-iris-py](https://scikit-learn.org/stable/auto_examples/cluster/plot_cluster_iris.html#sphx-glr-auto-examples-cluster-plot-cluster-iris-py)

此範例顯示了K-means演算法使用不同數量cluster，以及不同初始值設定產生的結果

1. 利用 datasets.load\_iris() 來讀取內建資料庫
2. 利用 KMeans 做分類
3. 利用 Axes3D 秀出結果

## (一)引入函式庫

引入函式如下:

1. numpy : 產生陣列數值
2. matplotlib.pyplot : 用來繪製影像
3. mpl\_toolkits.mplot3d import Axes3D : 繪製3D圖形
4. sklearn.cluster import KMeans : 切割cluster
5. sklearn import datasets : 用來匯入影像資料庫

```python
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn.cluster import KMeans
from sklearn import datasets
```

```python
np.random.seed(5)
```

隨機設定種子，可以用在 KMeans 裡 n\_init 的參數

```python
iris = datasets.load_iris()
X = iris.data
y = iris.target
```

iris = datasets.load\_iris() : 將一個dict型別資料存入iris

```python
for key,value in iris.items() :
    try:
        print (key,value.shape)
    except:
        print (key)
print(iris['feature_names'])
```

| 顯示                       | 說明                                         |
| ------------------------ | ------------------------------------------ |
| ('target\_names', (3L,)) | 共有三種鳶尾花 setosa, versicolor, virginica      |
| ('data', (150L, 4L))     | 有150筆資料，共四種特徵                              |
| ('target', (150L,))      | 這150筆資料各是那一種鳶尾花                            |
| DESCR                    | 資料之描述                                      |
| feature\_names           | 四個特徵代表的意義，分別為 萼片(sepal)之長與寬以及花瓣(petal)之長與寬 |

## (二)Clustering

```python
estimators = [('k_means_iris_8', KMeans(n_clusters=8)),
              ('k_means_iris_3', KMeans(n_clusters=3)),
              ('k_means_iris_bad_init', KMeans(n_clusters=3, n_init=1,
                                               init='random'))]
```

設定 KMeans 參數，各項參數設定如下:

* n\_clusters : 需要計算出的群集數
* init  : 設定初始化方式
* n\_init  : 使用不同 centroid seeds 運行 k-means 算法的時間

```python
fignum = 1
titles = ['8 clusters', '3 clusters', '3 clusters, bad initialization']
for name, est in estimators:
    fig = plt.figure(fignum, figsize=(4, 3))
    ax = Axes3D(fig, rect=[0, 0, .95, 1], elev=48, azim=134)
    est.fit(X)
    labels = est.labels_

    ax.scatter(X[:, 3], X[:, 0], X[:, 2],
               c=labels.astype(np.float), edgecolor='k')

    ax.w_xaxis.set_ticklabels([])
    ax.w_yaxis.set_ticklabels([])
    ax.w_zaxis.set_ticklabels([])
    ax.set_xlabel('Petal width')
    ax.set_ylabel('Sepal length')
    ax.set_zlabel('Petal length')
    ax.set_title(titles[fignum - 1])
    ax.dist = 12
    fignum = fignum + 1
```

Axes3D : 定義一個3D的圖形 est.fit : 根據上面 estimators 去 fit 資料庫的圖 ax.scatter : 畫散點圖，後面的參數用來調整顏色 ax.dist : 設定與物體之間的距離

![](https://github.com/kenny024241/machine-learning-python/blob/master/Clustering/ex10-1.png) ![](https://github.com/kenny024241/machine-learning-python/blob/master/Clustering/ex10-2.png) ![](https://github.com/kenny024241/machine-learning-python/blob/master/Clustering/ex10-3.png)

```python
fig = plt.figure(fignum, figsize=(4, 3))
ax = Axes3D(fig, rect=[0, 0, .95, 1], elev=48, azim=134)

for name, label in [('Setosa', 0),
                    ('Versicolour', 1),
                    ('Virginica', 2)]:
    ax.text3D(X[y == label, 3].mean(),
              X[y == label, 0].mean(),
              X[y == label, 2].mean() + 2, name,
              horizontalalignment='center',
              bbox=dict(alpha=.2, edgecolor='w', facecolor='w'))
# Reorder the labels to have colors matching the cluster results
y = np.choose(y, [1, 2, 0]).astype(np.float)
ax.scatter(X[:, 3], X[:, 0], X[:, 2], c=y, edgecolor='k')

ax.w_xaxis.set_ticklabels([])
ax.w_yaxis.set_ticklabels([])
ax.w_zaxis.set_ticklabels([])
ax.set_xlabel('Petal width')
ax.set_ylabel('Sepal length')
ax.set_zlabel('Petal length')
ax.set_title('Ground Truth')
ax.dist = 12

fig.show()
```

np.choose : 將原本 label 順序的(0 1 2)改成(1 2 0) ax.text3D : 將不同label的資料標上個別物種類名稱，裡面 X\[y == label, 3].mean() 用在調整 text 的 X Y Z 軸位置

![](https://github.com/kenny024241/machine-learning-python/blob/master/Clustering/ex10-4.png)

## (三)完整程式碼

Python source code:plot\_cluster\_iris.py

[https://scikit-learn.org/stable/\_downloads/plot\_cluster\_iris.py](https://scikit-learn.org/stable/_downloads/plot_cluster_iris.py)

```python
"""
=========================================================
K-means Clustering
=========================================================

The plots display firstly what a K-means algorithm would yield
using three clusters. It is then shown what the effect of a bad
initialization is on the classification process:
By setting n_init to only 1 (default is 10), the amount of
times that the algorithm will be run with different centroid
seeds is reduced.
The next plot displays what using eight clusters would deliver
and finally the ground truth.

"""
print(__doc__)


# Code source: Gaël Varoquaux
# Modified for documentation by Jaques Grobler
# License: BSD 3 clause

import numpy as np
import matplotlib.pyplot as plt
# Though the following import is not directly being used, it is required
# for 3D projection to work
from mpl_toolkits.mplot3d import Axes3D

from sklearn.cluster import KMeans
from sklearn import datasets

np.random.seed(5)

iris = datasets.load_iris()
X = iris.data
y = iris.target

estimators = [('k_means_iris_8', KMeans(n_clusters=8)),
              ('k_means_iris_3', KMeans(n_clusters=3)),
              ('k_means_iris_bad_init', KMeans(n_clusters=3, n_init=1,
                                               init='random'))]

fignum = 1
titles = ['8 clusters', '3 clusters', '3 clusters, bad initialization']
for name, est in estimators:
    fig = plt.figure(fignum, figsize=(4, 3))
    ax = Axes3D(fig, rect=[0, 0, .95, 1], elev=48, azim=134)
    est.fit(X)
    labels = est.labels_

    ax.scatter(X[:, 3], X[:, 0], X[:, 2],
               c=labels.astype(np.float), edgecolor='k')

    ax.w_xaxis.set_ticklabels([])
    ax.w_yaxis.set_ticklabels([])
    ax.w_zaxis.set_ticklabels([])
    ax.set_xlabel('Petal width')
    ax.set_ylabel('Sepal length')
    ax.set_zlabel('Petal length')
    ax.set_title(titles[fignum - 1])
    ax.dist = 12
    fignum = fignum + 1

# Plot the ground truth
fig = plt.figure(fignum, figsize=(4, 3))
ax = Axes3D(fig, rect=[0, 0, .95, 1], elev=48, azim=134)

for name, label in [('Setosa', 0),
                    ('Versicolour', 1),
                    ('Virginica', 2)]:
    ax.text3D(X[y == label, 3].mean(),
              X[y == label, 0].mean(),
              X[y == label, 2].mean() + 2, name,
              horizontalalignment='center',
              bbox=dict(alpha=.2, edgecolor='w', facecolor='w'))
# Reorder the labels to have colors matching the cluster results
y = np.choose(y, [1, 2, 0]).astype(np.float)
ax.scatter(X[:, 3], X[:, 0], X[:, 2], c=y, edgecolor='k')

ax.w_xaxis.set_ticklabels([])
ax.w_yaxis.set_ticklabels([])
ax.w_zaxis.set_ticklabels([])
ax.set_xlabel('Petal width')
ax.set_ylabel('Sepal length')
ax.set_zlabel('Petal length')
ax.set_title('Ground Truth')
ax.dist = 12

fig.show()
```
