100日後にエンジニアになるキミ - 83日目 - プログラミング - 機械学習について8

昨日までのはこちら

[100日後にエンジニアになるキミ - 76日目 - プログラミング - 機械学習について](https://qiita.com/otupy/items/6a4f960ba4df06e27050)

[100日後にエンジニアになるキミ - 70日目 - プログラミング - スクレイピングについて](https://qiita.com/otupy/items/f53e2e7d16adf80b5acf)

[100日後にエンジニアになるキミ - 66日目 - プログラミング - 自然言語処理について](https://qiita.com/otupy/items/5828ac7450c5ba8d6931)

[100日後にエンジニアになるキミ - 63日目 - プログラミング - 確率について1](https://qiita.com/otupy/items/0196897ae4d2134794fa)

[100日後にエンジニアになるキミ - 59日目 - プログラミング - アルゴリズムについて](https://qiita.com/otupy/items/f1a5e81633b868f3b5ed)

[100日後にエンジニアになるキミ - 53日目 - Git - Gitについて](https://qiita.com/otupy/items/0abaad82a7f3fea73f1f)

[100日後にエンジニアになるキミ - 42日目 - クラウド - クラウドサービスについて](https://qiita.com/otupy/items/d1765f1541a104ed6133)

[100日後にエンジニアになるキミ - 36日目 - データベース - データベースについて](https://qiita.com/otupy/items/7af17635d576677606dc)

[100日後にエンジニアになるキミ - 24日目 - Python - Python言語の基礎1](https://qiita.com/otupy/items/6d1e5453f530e07b7aec)

[100日後にエンジニアになるキミ - 18日目 - Javascript - JavaScriptの基礎1](https://qiita.com/otupy/items/2f71d5f9c754b29d9555)

[100日後にエンジニアになるキミ - 14日目 - CSS - CSSの基礎1](https://qiita.com/otupy/items/61a97863f6df14171994)

[100日後にエンジニアになるキミ - 6日目 - HTML - HTMLの基礎1](https://qiita.com/otupy/items/cd2315dcb38671cfded0)

今回は機械学習についてのお話の続きです。

## クラスタリングについて

初回で機械学習でできることについて解説していますが、機械学習でできることは
基本的には3つです。

・回帰
・分類
・クラスタリング

大まかに言うと`予測`になりますが何を`予測`するかと言う部分が変わります。

・回帰：数値を予測する
・分類：カテゴリを予測する
・クラスタリング：いい感じにする

クラスタリングは教師なし学習になり`答えは分からないけど何かいい感じに分ける`
ということを行うことができます。

今回使用するデータは`scikit-learn`に付属している`digits`(数字)のデータを用います。

### データの読み込み

まずは数字のデータを読み込みしてみましょう。
`load_digits`でデータを読み込みすることができます。

```python
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt
%matplotlib inline

digits = load_digits()
print(digits.data.shape)

plt.gray() 
plt.matshow(digits.images[0]) 
plt.show()
```
(1797, 64)
<Figure size 432x288 with 0 Axes>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/4f339942-8b99-e1cf-e447-e0e2a1cafb92.png)

画像として出力すると数字の`0`に見えますね。

8x8サイズの画像です。

それではこのデータの元を表示してみます。

```python
digits.images[0]
```
array([[ 0.,  0.,  5., 13.,  9.,  1.,  0.,  0.],
       [ 0.,  0., 13., 15., 10., 15.,  5.,  0.],
       [ 0.,  3., 15.,  2.,  0., 11.,  8.,  0.],
       [ 0.,  4., 12.,  0.,  0.,  8.,  8.,  0.],
       [ 0.,  5.,  8.,  0.,  0.,  9.,  8.,  0.],
       [ 0.,  4., 11.,  0.,  1., 12.,  7.,  0.],
       [ 0.,  2., 14.,  5., 10., 12.,  0.,  0.],
       [ 0.,  0.,  6., 13., 10.,  0.,  0.,  0.]])

データ自体は数値の羅列です。数値は16段階のグレースケールを表しており0が黒色、15が白になります。

この数値のデータを使っていい感じに分けてみましょう。
データフレームに読み込みしてみましょう。

```python
digits_df_tgt = pd.DataFrame(digits.target, columns=['target'])
digits_df_tgt.head()

digits_df = pd.DataFrame(digits.data)
digits_df.head()
```
|  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| 0 | 0 | 0 | 5 | 13 | 9 | 1 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 6 | 13 | 10 | 0 | 0 | 0 |
| 1 | 0 | 0 | 0 | 12 | 13 | 5 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 11 | 16 | 10 | 0 | 0 |
| 2 | 0 | 0 | 0 | 4 | 15 | 12 | 0 | 0 | 0 | 0 | ... | 5 | 0 | 0 | 0 | 0 | 3 | 11 | 16 | 9 | 0 |
| 3 | 0 | 0 | 7 | 15 | 13 | 1 | 0 | 0 | 0 | 8 | ... | 9 | 0 | 0 | 0 | 7 | 13 | 13 | 9 | 0 | 0 |
| 4 | 0 | 0 | 0 | 1 | 11 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 2 | 16 | 4 | 0 | 0 |

こんな感じの数字を各ピクセルの数値に数値に直したデータであることが確認できます。


### クラスタリングを行う

クラスタリングは大きく分けて二つの手法があります。

**階層クラスタリング**
トーナメント表のようなクラスタリング手法で、最も似ている組み合わせから順番にクラスターにしていく方法
途中過程が階層のように表すことができ最終的に`デンドログラム`(樹形図)ができます。
手法はウォード法、群平均法、最短距離法etcなど数多くあります。

**非階層クラスタリング**
異なる性質のものが混ざり合った集団から、互いに似た性質を持つものを集め、クラスターを作る方法の1つです。
手法としてK-meansなどがあります。


ここでは`K-means`を用いて非階層クラスタリングを行なってみましょう。

まずはライブラリを呼び出します。

`K-means`はとりあえず何個(K)に分けるだけを指定します。
データフレームを指定してクラスタリングです。

```python
from sklearn.cluster import KMeans

K=10
kmeans = KMeans(n_clusters=K).fit(digits_df) 
pred_label = kmeans.predict(digits_df)
pred_df = pd.DataFrame(pred_label,columns=['pred'])
```

これで予測結果も出ました。`pred_df`に予測結果を格納しています。

### 結果をみてみる



一応どんな感じで分かれたのかをみてみます。

```python
calc = {i:{} for i in range(K)}
for pred , target in zip(pred_label , digits.target):
    #print('予測 : {0} , 実測 : {1}'.format(pred,target))
    if target in calc[pred]:
        calc[pred][target]+=1
    else:
        calc[pred][target] =1
        
```
{0: {6: 177, 1: 2, 8: 2, 5: 1},
 1: {3: 154, 9: 6, 2: 13, 1: 1, 8: 2},
 2: {1: 55, 4: 7, 7: 2, 2: 2, 9: 20, 8: 5, 6: 1},
 3: {7: 170, 2: 3, 3: 7, 9: 7, 4: 7, 8: 2},
 4: {1: 99, 2: 8, 8: 100, 9: 1, 6: 2, 4: 4, 7: 2, 3: 7},
 5: {5: 43, 8: 53, 9: 139, 3: 13, 2: 2},
 6: {5: 136, 9: 7, 7: 5, 8: 7, 1: 1, 3: 2},
 7: {0: 177, 6: 1, 2: 1},
 8: {2: 148, 1: 24, 8: 3},
 9: {4: 163, 5: 2, 0: 1}}

K-meansクラスタリングは数値の性質を見て似たものどうしの分類をしK個に分類します。
ここで出しているものは`クラスター番号`です。クラスター番号の`0`は実際の値だと`6`の数字が一番多いようです。

実測と予測を見てみましょう。

```python
digits_df2 = pd.concat([pred_df,digits_df],axis=1)
digits_df2['pred'].value_counts()

index = list(digits_df[digits_df2['pred']==0].index)
print(index)
```
[6, 16, 26, 34, 58, 65, 66, 67, 82, 88, 104, 106, 136, 146, 156, 164, 188, 195, 196, 197, 212, 223, 232, 234, 262, 272, 282, 290, 314, 321, 322, 323, 338, 344, 351, 360, 362, 392, 402, 412, 420, 444, 451, 452, 453, 468, 474, 481, 490, 522, 532, 542, 550, 563, 569, 574, 581, 582, 583, 586, 598, 604, 611, 620, 622, 652, 662, 672, 680, 704, 711, 712, 713, 728, 734, 741, 750, 752, 782, 784, 802, 810, 834, 841, 842, 843, 858, 864, 871, 880, 882, 911, 921, 931, 939, 960, 967, 968, 969, 984, 989, 996, 1005, 1007, 1035, 1045, 1055, 1063, 1085, 1092, 1093, 1094, 1109, 1115, 1122, 1131, 1133, 1163, 1173, 1183, 1191, 1215, 1222, 1223, 1224, 1239, 1245, 1252, 1261, 1263, 1293, 1303, 1313, 1321, 1345, 1352, 1353, 1354, 1361, 1369, 1375, 1382, 1391, 1393, 1421, 1431, 1441, 1449, 1473, 1480, 1481, 1482, 1497, 1503, 1510, 1519, 1521, 1561, 1569, 1577, 1601, 1608, 1609, 1610, 1623, 1629, 1636, 1645, 1647, 1673, 1683, 1693, 1701, 1725, 1732, 1733, 1734, 1749, 1755, 1762, 1771, 1773]

クラスタ番号`0`のもののインデックス値をみて、そのデータの数字が何なのかを見てみましょう。

```
plt.gray() 
plt.matshow(digits.images[6]) 
plt.matshow(digits.images[16]) 
plt.matshow(digits.images[26]) 
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/4ee1b6ee-dd4a-7bc7-f33c-c240782cfbf5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/1c5a98ad-534a-72c7-c3f9-fb8ff8a653cf.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/cb811d31-a032-2792-bbcc-ce0869db98cc.png)

クラスタ番号`0`のやつは`6`っぽいですね。
いい感じに分けられたのではないでしょうか。

本来は答えが分からないけど、ユーザーを７つに分類したいとかの用途で用います。
データの特性から似たユーザーを分類分けしてくれる分けです。


## まとめ

本日はクラスタリングの仕組みを説明しました。
クラスタリングは他にもたくさん手法が存在します。

まずは、クラスタリングとは何、と言うことから初めてやり方を抑えておきましょう。

君がエンジニアになるまであと17日

## 作者の情報
乙pyのHP：
http://www.otupy.net/

Youtube：
https://www.youtube.com/channel/UCaT7xpeq8n1G_HcJKKSOXMw

Twitter：
https://twitter.com/otupython