機械学習-アヤメの分類 (プログラム)
機械学習としてTensorflow + Kerasでの教師あり学習のサンプルとしてアヤメの分類を行います。
アヤメの分類とはビックデータや人工知能で用いられる典型的な線形分離の問題としてあつかわれています。
使用するデータはAnacondaと共にインストールされたscikit-learnライブラリに同梱されており、アヤメの三種類150サンプルからなるデータセットが用意されています。
Tensorflow + Kerasを用いた教師あり学習でのサンプルとしてよく用いられており、scikit-learnライブラリを使用することで機械学習やデータマイニングをすぐに試すことが出来るようになっています。
アヤメの分類方法
アヤメを構成する花びらの長さや幅など4つの属性により、それぞれどのアヤメの種類に属するかを決定します。
アヤメを構成する4つの属性
- がく片の長さ
- がく片の幅
- 花びらの長さ
- 花びらの幅
それぞれの属性により、アヤメの以下の3種類に分類します。
- setosa(ヒオウギアヤメ)
- Versicolour(ブルーフラッグ)
- Virginica
こちらの記事でも説明しています。
教師あり学習方法
アヤメの分類方法としては次の通りに学習をしていきます。
①150個のサンプルデータを学習用120個、実験用30個に分割する。
②学習用120個のデータに対しアヤメの属性と種類をセットで学習させる。
③学習の質を高めるためエポック数を100にて行う。
④実験用データ30個に対して、アヤメの種類を推測させる。
⑤推測した結果と実際の結果を比較し正解率をを出力させる。
準備段階
scikit-learnを使用するためにインストールします。
1 |
conda install scikit-learn |
kerasについても必要のためインストールを行います。
1 |
conda install keras |
ソースコード
ソースコードです。個々の詳細については別途説明します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#scikit-learnからデータの取り出し from sklearn import datasets iris = datasets.load_iris() #アヤメの分類に使用するデータの確認 print(iris.DESCR) iris.data iris.target #アヤメの分類の学習 from sklearn.model_selection import train_test_split as split x_train, x_test, y_train, y_test = split(iris.data,iris.target,train_size=0.8,test_size=0.2) import tensorflow as tf import keras from keras.layers import Dense,Activation #ニュートラルネットワークで使用するモデル作成 model = keras.models.Sequential() model.add(Dense(units=32,input_dim=4)) model.add(Activation('relu')) model.add(Dense(units=3)) model.add(Activation('softmax')) model.compile(loss='sparse_categorical_crossentropy',optimizer='sgd',metrics=['accuracy']) #教師あり学習の実行 model.fit(x_train,y_train,epochs=100) #評価の実行 score = model.evaluate(x_test,y_test,batch_size = 1) print(score[1]) #1つのデータに対する評価の実行方法 import numpy as np x = np.array([[5.1,3.5,1.4,0.2]]) r = model.predict(x) print(r) r.argmax() |
ソースコードの詳細説明
scikit-learnからデータの取り出し
1 2 |
from sklearn import datasets iris = datasets.load_iris() |
インストールしたscikit-learnからデータベース(datasets)を取り出します。
データベース(datasets)には予め実験用データが同梱されているので、実験用データからアヤメの分類データ(iris)をロードします。
アヤメの分類に使用するデータの確認
アヤメの分類データには3種類の情報が含まれています。
・iris.DESCR:データの説明
・iris.data:アヤメの各種データ
・iris.target:アヤメの種類
1 |
print(iris.DESCR) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Iris Plants Database ==================== Notes ----- Data Set Characteristics: :Number of Instances: 150 (50 in each of three classes) :Number of Attributes: 4 numeric, predictive attributes and the class :Attribute Information: - sepal length in cm - sepal width in cm - petal length in cm - petal width in cm - class: - Iris-Setosa - Iris-Versicolour - Iris-Virginica :Summary Statistics: |
print(iris.DESCR)によりデータの説明が表示されます。
DESCR情報により、アヤメデータは150×4の2次元配列になっていることが分かります。
150×4の2次元配列は次のような構造となっており、アヤメを判断する属性が格納されています。
sepal length:がく片の長さ
sepal width :がく片の幅
petal length:花びらの長さ
petal width :花びらの幅
これらの4つの属性により、アヤメの品種を識別します。
アヤメの品種は「setosa」、「Versicolour」、「Virginica」の3種類が定義されています。
1 |
iris.data |
1 2 3 4 5 6 7 |
array([[ 5.1, 3.5, 1.4, 0.2], [ 4.9, 3. , 1.4, 0.2], [ 4.7, 3.2, 1.3, 0.2], [ 4.6, 3.1, 1.5, 0.2], [ 5. , 3.6, 1.4, 0.2], [ 5.4, 3.9, 1.7, 0.4], [ 4.6, 3.4, 1.4, 0.3], |
アヤメの各種データの表示しています。それぞれの属性は次の通りです。
[がく片の長さ,がく片の幅,花びらの長さ,花びらの幅]これらのデータは150の配列データとして保持されています。
1 |
iris.target |
1 2 3 4 5 6 7 |
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]) |
アヤメの種類の表示をしています。それぞれの数値の意味は次の通りです。
0:「setosa」
1:「Versicolour」
2:「Virginica」
こちらもiris.data同様に150個のデータが入っています。
アヤメの分類の学習
アヤメの分類の学習をしていきます。学習方法は次の通りです。
・150個のデータのうち120個を学習に用いる
・残りの30個のデータを実験用に用いる
1 2 |
from sklearn.model_selection import train_test_split as split x_train, x_test, y_train, y_test = split(iris.data,iris.target,train_size=0.8,test_size=0.2) |
150個のアヤメのデータをシャッフルし120個の学習用と30個の実験用のデータに分けます。
データを分ける際にscikit-learnのtrain_test_splitを用いますが、名前が長いのでsplitと別名に定義しています。
splitを用いてアヤメのデータを学習用:実験用(8:2)に分割します。
その結果120個のデータが学習用、30個のデータが実験用となります。
1 2 3 |
import tensorflow as tf import keras from keras.layers import Dense,Activation |
tensorflowとkerasをインポートします。tensorflowは別名tfとして定義しています。
kerasのレイヤーより、DenseとActivationのクラスインポートします。
Dense:ニューラルネット定義クラス
Activation:活性化関数クラス
ニュートラルネットワークで使用するモデル作成
ニュートラルネットワークで使用するモデルを作成します。
1 2 3 4 5 6 |
model = keras.models.Sequential() model.add(Dense(units=32,input_dim=4)) model.add(Activation('relu')) model.add(Dense(units=3)) model.add(Activation('softmax')) model.compile(loss='sparse_categorical_crossentropy',optimizer='sgd',metrics=['accuracy']) |
1行目:レイヤーの線形スタックであるSequentialモデルを適用します
2行目:中間層が32個、入力層が4個のニューロンを指定します
3行目:中間層の活性化関数にReLU関数を適用します
4行目:出力層を3個にします
5行目:出力層の活性化関数にsoftmax関数を適用します
6行目:compileでモデルを構築します。
loss :損失関数(コスト関数)、クロスエントロピー法を適用
optimizer:最適化アルゴリズム、確率的勾配降下法を適用
metrics :評価関数のリスト、正解率を適用
最後のニュートラルネットワークのコンパイルを行います。
教師あり学習の実行
1 |
model.fit(x_train,y_train,epochs=100) |
学習はmodel.fitという関数を起動します。epochsは繰り返し学習する回数を表しており、今回は100を指定しています。
機械学習では繰り返し学習をすることで入力層、中間層、出力層からなるニュートラルネットワークの重み(パラメータ)を最適化できます。
1 2 3 4 5 6 7 8 |
Epoch 1/100 120/120 [==============================] - 0s 2ms/step - loss: 1.7533 - acc: 0.3583 Epoch 2/100 120/120 [==============================] - 0s 75us/step - loss: 1.2617 - acc: 0.3583 Epoch 3/100 120/120 [==============================] - 0s 83us/step - loss: 1.1032 - acc: 0.3583 Epoch 4/100 120/120 [==============================] - 0s 100us/step - loss: 1.0327 - acc: 0.3583 |
評価の実行
1 |
score = model.evaluate(x_test,y_test,batch_size = 1) |
1 |
1/30 [.............................] - ETA: 0s |
今回の実験では30回の実験用データに対して29個正解 1個失敗していました。
1 |
print(score[1]) |
1 |
0.966666666667 |
score[1]を指定することで正解率が分かります。
正解率は約97%でした
1つのデータに対する評価の実行方法
今までは全てのデータを一気に実験していたために過程が見えませんでした。
そこで1つのデータに着目し過程を見ていくことにします。
1 2 3 |
import numpy as np x = np.array([[5.1,3.5,1.4,0.2]]) r = model.predict(x) |
1つのデータのアヤメの属性として次のように設定しています。
がく片の長さ:5.1
がく片の幅:3.5
花びらの長さ:1.4
花びらの幅:0.2
としてそれがどのアヤメの種類に該当するか確認します。
1 |
print(r) |
1 |
[[ 0.94546139 0.05294686 0.0015918 ]] |
与えられたデータに対してのアヤメの種類の確立が表示されています。
「setosa」:98%
「Versicolour」:0.018%
「Virginica」:0.0012%
とのことによりアヤメの種類は一番確立が高い「setosa」と想定することができます。
1 |
r.argmax() |
1 |
argmaxを起動することでも簡単に最も確率の高い分類を判定できます。
0と表示されていることから、「setosa」を想定していることが分かります。