簡単な分類問題を解いてみる

目標

機械学習の効果を確認するために、簡単な分類問題を解いてみよう。

データ

以下のようなデータをpythonで出力する。

f:id:kpsdr:20171104203620j:plain

     図1 散布図

エリアごとに色分けされたデータが散らばっていることがわかる。

各点の色は座標(x1,x2)によって定まるようである。

グラフのデータを機械学習で利用しやすい形に持ち込む。

f:id:kpsdr:20171104205333j:plain

       図2 行列データ

図2において、1行目はx1 =0.031295,x2=0.284174の座標に赤点を存在することをします。

モデル

f:id:kpsdr:20171105184435j:plain
図3モデル

プログラム

今のプログラムの目的は、学習の経過を示すグラフの出力と新データに対して正しくラベル(色)が予測されているかを確認することである。

import keras
from keras.layers import Input, Dense#,Dropout
from keras.models import Model
import numpy as np
import matplotlib.pyplot as plt
from keras.optimizers import RMSprop


#データを作成

# generate data
x1_r = np.random.rand(100)*0.5
x2_r = np.random.rand(100)*0.5

#label 1(red)
l_r = np.zeros_like(x1_r)
l_r = l_r + 0

x1_b = np.random.rand(100)*0.5 + 0.5
x2_b = np.random.rand(100)*0.5

#label 2(blue)
l_b = np.zeros_like(x1_b)
l_b = l_b + 1


x1_g = np.random.rand(100)*0.5
x2_g = np.random.rand(100)*0.5 + 0.5

#label 3(green)
l_g = np.zeros_like(x1_g)
l_g = l_g + 2


x1_y = np.random.rand(100)*0.5 + 0.5
x2_y = np.random.rand(100)*0.5 + 0.5

#label 4(yellow)
l_y = np.zeros_like(x1_y)
l_y = l_y + 3

#array merge
A_r = np.c_[x1_r,x2_r,l_r]
A_b = np.c_[x1_b,x2_b,l_b]
A_g = np.c_[x1_g,x2_g,l_g]
A_y = np.c_[x1_y,x2_y,l_y]


A = np.r_[A_r,A_b,A_g,A_y]

#shuffle
np.random.shuffle(A)


#split トレイン用データとテスト用データを分離
data,label = np.hsplit(A,[2])
#data_train :(300,2) date_test :(100,2) 
data_train,data_test = np.vsplit(data,[300])
#label_train :(300,1) label_test :(100,1)  
label_train,label_test = np.vsplit(label,[300])

label_train = keras.utils.np_utils.to_categorical(label_train.astype('int32'),4)
label_test = keras.utils.np_utils.to_categorical(label_test.astype('int32'),4)


#ニューラルネットワークのモデルを定義
#入力層 2入力
inputs = Input(shape=(2,))
#隠れ層 3出力で活性化関数ははrelu
nw = Dense(3, activation='relu')(inputs)
#出力層 4出力 ソフトマックス関数を挿入(0~1の値に収める)
predictions = Dense(4, activation='softmax')(nw)

#モデルをまとめる
model = Model(inputs=inputs, outputs=predictions)
#モデルをコンパイル  最適化手法:RMSprop 目的関数:categorical_crossentropy
model.compile(optimizer=RMSprop(),
              loss='categorical_crossentropy',
              metrics=['accuracy'])
#学習の実行 epochsは学習回数 historyには学習の経過が記録される。
history = model.fit(data_train, label_train, batch_size=10, epochs=150, verbose=1,validation_data=(data_test, label_test))

#学習の経過をグラフ化
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()


#新データに対する予測
xa = np.array([[0.8,0.7]])
print("新データ(0.8,0.7)に対する予想")
print(model.predict(xa))

出力

f:id:kpsdr:20171106212010j:plain
図4 認識精度の推移


epoch(学習回数)が増えるごとに認識精度が向上していることが見て取れる。

新データ(0.8,0.7)に対する予想
[[ 0.00191311  0.06421792  0.00333812  0.93053085]]

学習済みのニューラルネットワークは新データ(0.8,0.7)に対して4番目の要素(黄色に対応)である確率が
0.93053085でもっとも高いと予想している。
図1を見てみるとデータ(0.8,0.7)には黄色のラベルが付されそうである。
人間の判断とニューラルネットワークの判断が一致している。
このニューラルネットワークは正確な分類器として機能しているようである。

まとめ

非常に簡単なデータにたいして、ニューラルネットワークをトレーニングさせ、高精度の分類器を実現できた。
今回はepoch数を150に設定したが、50に設定しトレーニングすると、認識精度は150のときのそれに及ばなかった。つまり、epoch数を増やすことで認識精度が向上する様子を観察できた。
さらなる認識精度の向上には、さまさまな手法が存在するが、またの機会に記事にしたい。