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


昨日までのはこちら

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

100日後にエンジニアになるキミ - 70日目 - プログラミング - スクレイピングについて

100日後にエンジニアになるキミ - 66日目 - プログラミング - 自然言語処理について

100日後にエンジニアになるキミ - 63日目 - プログラミング - 確率について1

100日後にエンジニアになるキミ - 59日目 - プログラミング - アルゴリズムについて

100日後にエンジニアになるキミ - 53日目 - Git - Gitについて

100日後にエンジニアになるキミ - 42日目 - クラウド - クラウドサービスについて

100日後にエンジニアになるキミ - 36日目 - データベース - データベースについて

100日後にエンジニアになるキミ - 24日目 - Python - Python言語の基礎1

100日後にエンジニアになるキミ - 18日目 - Javascript - JavaScriptの基礎1

100日後にエンジニアになるキミ - 14日目 - CSS - CSSの基礎1

100日後にエンジニアになるキミ - 6日目 - HTML - HTMLの基礎1

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

クラスタリングについて

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

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

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

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

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

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

データの読み込み

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

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)

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

8x8サイズの画像です。

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

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が白になります。

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

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)に分けるだけを指定します。
データフレームを指定してクラスタリングです。

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に予測結果を格納しています。

結果をみてみる

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

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の数字が一番多いようです。

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

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



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

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

まとめ

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

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

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

作者の情報

乙pyのHP:
http://www.otupy.net/

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

Twitter:
https://twitter.com/otupython