Keras/Tensorflowを使った手書き文字MNISTデータセットの画像分類(MLP)
はじめてのディープラーニング。まずは簡単なコードで動くかな?
ナノネ、今回はPythonでディープラーニング(Deep Learning)を試してみよう。
Tensorflowとか使うやつだよね?手持ちの古いPCで動くの?
GoogleのColaboratoryというクラウドサービスを使うから大丈夫だよ。Googleアカウントとブラウザーだけあれば、特に設定不要で高スペックなPython環境を利用できるから便利だよ。Jupyterノートブックでコーティングができて、ライブラリも追加可能、さらにGPUも使えるよ。しかもキホン無料、ありがたいよね。
それなら大丈夫かも。古いPCで四苦八苦してたけど、これからはディープラーニングも実践練習できそうだね。
さっそくだけど、ディープラーニングのコードを動かしてみよう。今回使うデータは定番の手書き数字MNISTを使うよ。サンプルコードも沢山あるしね。
まずは、必要なライブラリをインポートするよ。Colaboratoryだと主要なライブラリはデフォルトでインストール済みだから、importするだけでOK。(もしローカルなどで動かす場合は、利用環境に応じて必要なライブラリをインストールしてね)
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
kerasっていうのを使うの?
Kerasはディープラーニング用ライブラリで、Tensorflow(CNTK、Theanoなども利用可能)を容易に実行できるようにする便利なライブラリだよ。今回使う環境でも、KerasのバックエンドでTensorflowが動く設定になっているよ。
続いてMNISTデータセットの読み込み。
# データセット読み込み(学習用、検証用)
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# データ数と次元(確認)
print('X_train {}'.format(X_train.shape)) # 学習用画像データ
print('y_train {}'.format(y_train.shape)) # 学習用正解ラベル
print('X_test {}'.format(X_test.shape)) # 検証用画像データ
print('y_test {}'.format(y_test.shape)) # 検証用正解ラベル
手持ちでデータを準備しなくていいからラクチン。学習用が60,000件、検証用が10,000件。けっこう一杯あるね。
学習用の数字にどんな画像があるか、少しだけ確認してみよう。
# 学習画像データを一部だけ可視化(画像確認)
fig, axes = plt.subplots(10, figsize=(10, 15))
for i in range(10):
imgs = X_train[y_train == i][:10]
axes[i].imshow(imgs.transpose(1, 0, 2).reshape(28, 28 * 10), cmap='gray')
axes[i].axis('off')
axes[i].set_title("Number({})".format(i))
ヘンテコな形の数字も混じっているけど。気にしないことにする。
次はデータを少々変換。今回つくるモデルで扱いやすい形に変換しておくよ。
画像データは2次元を1次元にして、0から1.0に正規化。正解ラベルはOne-hot化しているよ。
# データ変換
X_train = X_train.reshape(60000, 784) # 画像データを一次元に変換 28x28->784
X_test = X_test.reshape(10000, 784)
X_train = X_train.astype('float32') # unit8 -> float32
X_test= X_test.astype('float32')
X_train /= 255 # 画像データ(0~255)を0~1.0に正規化
X_test /= 255
# 正解ラベルOne-hot化
num_classes = 10 # MNISTラベルの種類(数字0~9)
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
# 正解ラベルOne-hot化(データ確認)
fig = plt.figure(figsize=(10,6))
for i in range(6):
ax = fig.add_subplot(2, 3, i+1, xticks=[], yticks=[])
ax.imshow(X_train[i].reshape(28, 28), cmap='gray')
ax.set_title(str(y_train[i]))
正解ラベル(0から9)は、カテゴリ化されて該当のところだけ1が入っているね。
次はモデルの構築。調べてみるとSequentialとFunctioanlAPIを使ったモデル構築方法があるみたい。今回は、より簡単そうなSequentialモデルを使ってみよう。
まず、Sequential()でモデルのインスタンスを作って。あとはモデルにadd()で、任意の層を追加していけばOK(くわしい説明はまだできないけど...)。
層の追加で利用しているDenseというのは、全結合のニューラルネットワークだよ。第一引数にノード数、Activationで活性化関数を指定するよ。今回、ノード数は試しで適当な値、活性化関数はReLUを指定しているよ。
Dropoutっていうのは?なんか捨てちゃうの?
Dropoutは過学習防止に役立つ処理で、学習中、ランダムに入力ユニットの値を0にする割合が指定できるよ。
それから、最初の層だけは、input_shapeで入力データの形式をタプルで指定してね。今回は784(画像28x28)をタプルで指定すればOKだよ。
# モデル構築
# シーケンシャルモデル
model = Sequential()
# Layer1(隠れ層)
# ノード数: 512
# 活性化関数: ReLU
# 入力: 784次元
# ドロップアプト比: 0.2
model.add(Dense(512, activation='relu', input_shape=(784,)))
model.add(Dropout(rate=0.2))
# Layer2(隠れ層)
# ノード数: 256
# 活性化関数: ReLU
# ドロップアプト比: 0.2
model.add(Dense(256, activation='relu'))
model.add(Dropout(rate=0.2))
# Layer3(隠れ層)
# ノード数: 128
# 活性化関数: ReLU
# ドロップアプト比: 0.2
model.add(Dense(128, activation='relu'))
model.add(Dropout(rate=0.2))
# Layer4(出力層)
# ノード数: 10
# 活性化関数: SOFTMAX
model.add(Dense(10, activation='softmax'))
model.summary()
ラストは出力層になるから、ノード数は分類したい数に合わせてね。今回は数字10通りだから10だよ。それと出力層の活性化関数には、多クラス分類でよく利用されるソフトマックス関数(0~1の実数値で総和が1となる値を出力)を指定しているよ。
づづいて、モデルのコンパイル。どんな風に学習を行うかを設定するんだ。必要な設定は最適化アルゴリズム、損失関数、評価関数リストの3つだよ。
今回はサンプルコードなどを参考にして、最適化アルゴリズムはRMSprop、損失関数はcategorical_crossentropy、評価関数にaccuracyを指定しているよ(別の手法など詳しくはドキュメントを調べてね)。
# モデルのコンパイル(最適化アルゴリズム、損失関数、評価関数リストを指定)
model.compile(optimizer=RMSprop(),
loss='categorical_crossentropy',
metrics=['accuracy'])
やっと学習だね。。。
学習はfit()で実行できるよ。最初の引数には学習用のデータ(X_train)と正解ラベル(y_train)を渡してね。
batch_sizeはデータをまとめて処理する件数で、学習中はバッチ単位処理が終わるとモデルが1回更新されるみたいだよ。epochsはデータセットを何回分学習するかを指定。verboseは学習中のログ出力有無を指定できるよ。あとvalidation_dataは、検証用のデータと正解ラベルを指定すればOK。
ラジャー、学習実行!
# 学習
batch_size = 128 # バッチサイズ
epochs = 8 # エポック
history = model.fit(X_train, y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_data=(X_test, y_test))
無事学習できたみたいだけど、GPU使うと早いね。
最後は検証データで、モデルを評価。
無事学習できたみたい。やっぱりGPU使うと学習が早いね。
# モデル評価
score = model.evaluate(X_test, y_test, verbose=0)
print('Test loss:', np.round(score[0], 4))
print('Test accuracy:', score[1])
正答率は98%前後。データの中にはヘンテコな数字画像もたくさんありそうだけど、分類結果は結構優秀かも。
参考までに、学習履歴もプロットしておくね。
# モデル学習履歴をグラフで可視化
import matplotlib.pyplot as plt
#accuracy
plt.plot(range(1, len(history.history['acc'])+1), history.history['acc'])
plt.plot(range(1, len(history.history['val_acc'])+1), history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='best')
plt.show()
#loss
plt.plot(range(1, len(history.history['loss'])+1), history.history['loss'])
plt.plot(range(1, len(history.history['val_loss'])+1), history.history['val_loss'])
plt.title('model accuracy')
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='best')
plt.show()
今回のディープラーニングの練習は以上で。次回は畳み込み(CNN)を実践する予定だよ。
お疲れ様でした。またね!
0 件のコメント :
コメントを投稿