こんにちは!けいです.今回は,ラズパイでAIを動かすシリーズの4回目ということで,scikit-learnのニューラルネットワークを使った分類を行いたいと思います.
目次
プログラム
早速プログラムを見ていきましょう.
from sklearn import datasets
from sklearn.neural_network import MLPClassifier
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
# アヤメのデータをロードし、変数irisに格納
iris = datasets.load_iris()
# 特徴量のセットを変数Xに、ターゲットを変数yに格納
X = iris.data
y = iris.target
# 特徴量を外花被片の長さ(sepal length)と幅(sepal width)の
# 2つのみに制限(2次元で考えるため)
X = X[:,:2]
# 分類用に多層ニューラルネットワークを用意
clf = MLPClassifier(hidden_layer_sizes=(100, ), max_iter=10000, tol=0.00001, random_state=None)
# ニューラルネットワークの学習
print('学習中…')
clf.fit(X, y)
##### 分類結果を背景の色分けにより表示
# 外花被片の長さ(sepal length)と幅(sepal width)の
# 最小値と最大値からそれぞれ1ずつ広げた領域を
# グラフ表示エリアとする
x_min = min(X[:,0]) - 1
x_max = max(X[:,0]) + 1
y_min = min(X[:,1]) - 1
y_max = max(X[:,1]) + 1
# グラフ表示エリアを縦横400ずつのグリッドに区切る
# (分類クラスに応じて背景に色を塗るため)
XX, YY = np.mgrid[x_min:x_max:400j, y_min:y_max:400j]
# グリッドの点をscikit-learn用の入力に並べなおす
Xg = np.c_[XX.ravel(), YY.ravel()]
# 各グリッドの点が属するクラス(0~2)の予測をZに格納
Z = clf.predict(Xg)
# グリッド上に並べなおす
Z = Z.reshape(XX.shape)
# クラス0 (iris setosa) がlightcoral
# クラス1 (iris versicolor) がaqua
# クラス2 (iris virginica) がgreenyelllow
cmap0 = ListedColormap([(0, 0, 0, 0), "lightcoral"])
cmap1 = ListedColormap([(0, 0, 0, 0), "aqua"])
cmap2 = ListedColormap([(0, 0, 0, 0), "greenyellow"])
# グラフウインドウの大きさを横長に定める。
plt.subplots(figsize=(12, 5))
# 縦に1枚、横に2枚のグラフの1枚目を設定
plt.subplot(1, 2, 1)
# 背景の色を表示
plt.pcolormesh(XX, YY, Z==0, cmap=cmap0)
plt.pcolormesh(XX, YY, Z==1, cmap=cmap1)
plt.pcolormesh(XX, YY, Z==2, cmap=cmap2)
# 軸ラベルを設定
plt.xlabel('sepal length')
plt.ylabel('sepal width')
##### ターゲットに応じた色付きでデータ点を表示
# iris setosa (y=0) のデータのみを取り出す
Xc0 = X[y==0]
# iris versicolor (y=1) のデータのみを取り出す
Xc1 = X[y==1]
# iris virginica (y=2) のデータのみを取り出す
Xc2 = X[y==2]
# iris setosa のデータXc0をプロット
plt.scatter(Xc0[:,0], Xc0[:,1], c='lightcoral', linewidths=0.5, edgecolors='black')
# iris versicolor のデータXc1をプロット
plt.scatter(Xc1[:,0], Xc1[:,1], c="aqua", linewidths=0.5, edgecolors='black')
# iris virginica のデータXc2をプロット
plt.scatter(Xc2[:,0], Xc2[:,1], c="greenyellow", linewidths=0.5, edgecolors='black')
# 縦に1枚、横に2枚のグラフの2枚目を設定
plt.subplot(1, 2, 2)
# 損失関数のグラフの軸ラベルを設定
plt.xlabel('time step')
plt.ylabel('loss')
# グラフ縦軸の範囲を0以上と定める
plt.ylim(0, max(clf.loss_curve_))
# 損失関数の時間変化を描画
plt.plot(clf.loss_curve_)
print("学習回数:" + str(len(clf.loss_curve_)))
print("損失関数の値:" + str(clf.loss_curve_[-1]))
# 描画したグラフを表示
plt.show()
このコードは 『Raspberry piではじめる機械学習』を参考にしたものです.
以下のサイトでソースコードをダウンロードできます.
http://bluebacks.kodansha.co.jp/books/9784065020524/appendix/
実行結果
学習回数:1695
損失関数の値:0.3762432011453603
損失関数の値が低いということは,学習が進んだってことだよ
ボクの脳も,損失関数の値が小さいノカ??
プログラム解説
用いるデータ
scikit-learnのirisデータは,4つの特徴量がありますが,4次元を表現することができないため,今回は2つの特徴量を用います.
4つの特徴量を2つの特徴量に次元削除を行っているのが,16行目です.
正解ラベルはデフォルトの3つを使うので,変更しません.
ニューラルネットワーク
学習を行う機械学習モデルは,ニューラルネットワークを用います.
clf = MLPClassifier(hidden_layer_sizes=(100, ), max_iter=10000, tol=0.00001, random_state=None)
入力としては,2つの特徴量(sepal length,sepal width)を用いるので,入力層は2つのパーセプトロンです.
中間層は,コードのhidden_layer_sizesのパラメータを変えることで調整できます.今回はデフォルトの100個としました.
MLPClassifierは,出力として複数のクラスに分類することができます.出力層はソフトマックス関数です.ある入力の出力として,3つのクラスの確率が最も高いものに分類されます.
max_iter=10000は,最大エポック数です.エポック数とは,シナプス強度を調整する回数です.1エポックで,アヤメのデータ150個全部を使います.もし,10000エポック学習を行うと,(150×10000=1500000)150万個のデータで学習したことになります.
tol=0.00001とは,損失係数の減少がtol以下になったら学習をやめるという値です.つまりtolが小さいほど,より学習を繰り返します.
背景,データ点の描画
これらについては,以前の記事で解説していますので,そちらを参照ください.
パラメータを変化させる
今回のプログラムでは,中間層が100個でだいたい2000~3000回で学習が終わります.
そこで,中間層を400に変更して,10000回を強制的に学習させてみます.
プログラムの19行目をこのように変化させてみます.
clf = MLPClassifier(hidden_layer_sizes=(400, ), max_iter=10000, tol=-1, random_state=None)
hidden_layer_sizesを400にして,tol=-1とします.これは損失関数が1以上大きくなったら学習をストップするという意味です.損失関数が小さくなるように学習するため,大きくなることはあり得ないので,最大エポック数だけ学習します.
結果
学習回数:10000
損失関数の値0.29341115385122685
中間層の数を増やし,学習回数も増えたことで,先ほどよりも複雑な境界線を学習しました.
損失関数の値も小さくなり,学習はより進んだことが分かります.
まとめ
今回はニューラルネットワークを用いて,2次元データから3つのクラスに分類をしました.
自分自身も機械学習を勉強中ですが,良い本を見つけることが一番早く上達すると思います.
今回のプログラムは以下の本を参考にしたものなので,より機械学習について学んでみたいという方はぜひ読んでみて下さい.
また,ラズベリーパイを触るのが初めてという方には以下の本をおすすめします.
初心者でも安心だワン!!
ニューラルネットワーク,ボクの頭もそれで作られてるノカ??