scikit-learnを用いた多クラス分類(3/3)

scikit-learnを用いた多クラス分類として、前回までにk-近傍法ロジスティック回帰SVMを用いた分類を紹介しました.今回は、決定木による分類と最後に教師なし学習の例としてk-means法によるクラスタリングの紹介を行います.


前回の記事 scikit-learnを用いた多クラス分類(2/3) - 他力本願で生き抜く(本気)


## 準備(必要なライブラリ、データセットの準備)
# 必要なライブラリのimport
import numpy as np
import matplotlib.pyplot as plt

# データセットのインポート
from sklearn.datasets import load_iris
# データセットを訓練用・テスト用に分けるツールのインポート
from sklearn.model_selection import train_test_split

#irisにデータを保存
iris = load_iris()

# データセットを訓練データとテストデータに分ける
X_train, X_test, y_train, y_test = \
train_test_split(iris.data, iris.target)

決定木(Decision Tree)

決定木による分類では、Yes/NOで答えられる質問を通してデータを分類する階層的な木構造を学習します.決定木には分類木と回帰木の2つがあり、分類木は対象の分類に、回帰木は数値を推定する問題に使うことができます.

アヤメの例では、がくの長さは6.0cm以上か、といった具合に質問を繰り返す木を成形し、最終的に末端(葉)に辿り着き、どのアヤメの種類かを判定することになります。

今回の実装は、アヤメの分類が対象となるため、DecisionTreeClassifier (分類木)を使用します。max_depth がツリーの深さで、質問数になります。
質問が多すぎると、訓練データに過剰に適合してしまう過学習となります。テストデータに対する精度が落ちてしまいます.

決定木の結果は、graphvisを使うことで、計算したツリー構造を可視化することができます.使いこなして資料にさらっと載せたいですね.

決定木について詳しく知りたい場合は下記サイトが図解つきで非常に参考になります.決定木もアルゴリズムだと思っていたのですが、決定木はあくまでモデルであり、C4.5やCARTというのがアルゴリズムなんだそうです.ちょっと頭が熱くなってきました.
mathwords.net

from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import export_graphviz
from IPython.display import Image, display_png
import pydotplus as pdp

for max_depth in  [1, 2, 3]:
    clf = DecisionTreeClassifier(max_depth=max_depth)
    clf.fit(X_train, y_train)
    print(clf.score(X_test, y_test), "max_depth = %s" % (max_depth))
    
# 描画:
    file_name2 = "./iris_decision_tree_%s.png" % (max_depth)
    dot_data = export_graphviz(clf, out_file=None, class_names = iris.target_names\
               , feature_names = iris.feature_names, impurity = False\
               , filled = True)
    
    graph2 = pdp.graph_from_dot_data(dot_data)
    graph2.write_png(file_name2)

    # png_file: str
    display_png(Image(file_name2))

0.631578947368421 max_depth = 1
0.9210526315789473 max_depth = 2
0.9210526315789473 max_depth = 3

ランダムフォレスト(Random Forest)

ランダムフォレストは異なる決定木をたくさん作り、全ての決定木で予測した結果からもっとも確率が高くなるラベルを正解とするものです。
個々の木だと過学習となるかもしれませんが、複数の決定木による結果を集約することで過学習を抑制する効果があります。
実装には、RandomForestClassifier を使います。

from sklearn.ensemble import RandomForestClassifier


clf = RandomForestClassifier(n_estimators = 10, random_state = 0)
clf.fit(X_train, y_train)
print(clf.score(X_test, y_test))

0.9473684210526315

もっと具体的な問題で試したい方は以下の記事が参考になるかと思います:
Python scikit-learnのランダムフォレストで受診予約のNo-Showを予測する - け日記


k-means法

いよいよ最後になります.もう疲れ切って、ただのCopyPaste and Run マシーンと化してます.

k-means法は、教師なしのデータを、指定したk個のクラスに分類する方法です.教師データを持たない、入力データのクラスタリングなどに使われます.

k-means法のアルゴリズムの概要は下記です
1. 各データにランダムにクラスタを割り当てる(ランダムにラベルを付けると思ってください)
2. クラスタ(同じラベルを付けたデータ)の重心を計算する
3. 各点のクラスタを、最も近い重心のラベルに変更する
4. ラベルに変化がなくなれば終了.変化があれば2. 3.を繰り返す

実装は、sklearn.clusuterのKMeansを使います.

いくつのクラスタに分けるかは、n_clustersで指定する必要があります.

また今回、クラスリングの結果は図で示した方が分かりやすいため、元の記事にもありましたdef decision_boundary関数を拝借して決定境界を図化しています.scikit-learn公式にも載せてあるこちらがベースになっています.

X = iris.data[:, [0, 2]] 
y = iris.target

# graph common settings
h = .02  # step size in the mesh
x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))

# 決定境界を図化
def decision_boundary(clf, X, y, ax, title):
    clf.fit(X, y) # Kmeansの場合、yは無視されるのでclf.fit(X)としてもよい.

    # Plot the decision boundary. For that, we will assign a color to each
    # point in the mesh [x_min, x_max]x[y_min, y_max].    
    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])

    # Put the result into a color plot
    Z = Z.reshape(xx.shape)
    ax.pcolormesh(xx, yy, Z, cmap=plt.cm.Paired)

    # Plot also the training points
    ax.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', cmap=plt.cm.Paired)

    # label
    ax.set_title(title)
    ax.set_xlabel('sepal length')
    ax.set_ylabel('petal length')
  • こっちがメイン:
from sklearn.cluster import KMeans

fig, axes = plt.subplots(1, 4, figsize=(12, 3))

for ax, n_clusters in zip(axes, [2, 3, 4, 5]):
    title = "n_clusters=%s"% (n_clusters)
    clf = KMeans(n_clusters=n_clusters)
    decision_boundary(clf, X, y, ax, title)
  • 結果
    • 元々は3クラスに関係なく、n_clustersで指定したクラス数に分類しています.

f:id:shirakonotempura:20181219012713p:plain
k-means法によるクラスタリングの可視化

参考:
詳しくクラスタリングを知りたい人はこちらが参考になります:
30分でわかる機械学習用語「クラスタリング(Clustering)」 - Qiita

さらに詳しくクラスタリングを知りたい人はこちらが参考になります:
クラスタリング (クラスター分析)


以上です.やっと終わりました.あらためて見るとまさに他力本願.
でも、Markdownで書くことに大分慣れてきました.Texによる数式も使えるみたいなのでそちらにも慣れていきたいと思います.


誤字・脱字・勘違い、お気づきの場合はコメントいただければ幸いです.


次は、NNを使った画像識別を記事にしたいと思っています.
でもプロフィール画像を作りたいので、GANにでも挑戦してみたい・・.