Keras/Tensorflowを使った手書き文字MNISTデータセットの画像分類(CNN)
畳み込みを使ったCNNで画像分類をやってみよう
ナノネ、前回の続きでKeras(+TensorFlow)を使ってDeep Learningを試してみよう。
今回もデータは、手書き数字MNISTを使うの?
うん、またMNISTを使うよ。前回は全結合層だけでモデルを組んだけど、今回は畳み込み層を入れたCNN(Convolutional Neural Network)という手法で画像を分類してみよう。
畳み込みをすると、何かいいことあるの?
畳み込みを使うと、データの空間的な特徴を効率的に捉えることができるよ。畳み込みを使ったCNNは、画像認識でよく利用される手法だよ。
今回もGoogle Colaboratoryの環境を使ってコードを書くよ。(もしローカルなどで動かす場合は、利用環境に応じて必要なライブラリを準備してね)
# Colaboratory環境 @2019/05 ****
# Ubuntu 18.04.2 LTS
# Python 3.6.7
# :Keras 2.2.4
# :tensorflow 1.13.1
# :numpy 1.16.3
# :matplotlib 3.0.3
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
インポートは前回と少しだけ違うね。keras.layersのFlatten、Conv2D、Maxpooling2Dとか増えてる。
# データセット読み込み(学習用、検証用)
(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:20] # 各数字10個
axes[i].imshow(imgs.transpose(1, 0, 2).reshape(28, 28 * len(imgs)), cmap='gray')
axes[i].axis('off')
axes[i].set_title("Number({})".format(i))
数字画像のイメージチェックまで完了。
データを変換するところが、前回と少し違うから注意ね。
# 画像次元(画像サイズ)
img_rows, img_cols = 28, 28
Kerasのバックエンドによってチャンネルの指定順が違うようなので、サンプルコード(mnist_cnn.py)の場合分けをそのまま引用。TensorflowだとChanels_Lastだったので、(画像行数、画像列数、画像ch数)の順でよさげ。
# Kerasのバックエンド(Tensorflow、Theanoなど)で入力チャンネルの順番が違うため場合分けする
if K.image_data_format() == 'channels_first':
X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols)
X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols)
input_shape = (1, img_rows, img_cols)
else: # 'channels_last'
X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 1)
X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
# 確認 -> Tensorflowの場合、channel_last
K.image_data_format()
画像データを0~1の実数に正規化、正解ラベルをOne-Hot化するのも前回と一緒だよ。
# データ正規化
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(3):
ax = fig.add_subplot(1, 3, i+1, xticks=[], yticks=[])
ax.imshow(X_train[i].reshape(28, 28), cmap='gray')
ax.set_title(str(y_train[i]))
データ準備はOK。このあとはモデル構築だね。
前回同様、Sequentialモデルで構築しよう。
# モデル構築
# シーケンシャルモデル
model = Sequential()
# 畳み込み層(フィルター)
model.add(Conv2D(32, kernel_size=(3, 3),
activation='relu',
input_shape=input_shape))
# 畳み込み層(フィルター)
model.add(Conv2D(64, (3,3), activation='relu'))
# プーリング層(縮小)
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten()) # 一次元に戻す
# 全結合層層
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
# 出力層
model.add(Dense(num_classes, activation='softmax'))
model.summary()
ざっくりだけど、Conv2Dは畳み込み層で、3×3サイズのフィルター処理をおこなっているよ。
Maxpooling2Dはプーリング層で、2×2サイズの最大値を採用してデータの縮小処理をおこなっているよ。
畳み込みとプーリングが終わったら、Flatten()でデータを1次元に戻してから全結合層へ。後半の部分は前回とだいだい一緒だね。
づづいて、モデルのコンパイル。最適化アルゴリズム、損失関数、評価関数リストの3つ指定するよ。
# モデルのコンパイル(最適化アルゴリズム、損失関数、評価関数リストを指定)
model.compile(optimizer=keras.optimizers.adadelta(),
loss=keras.losses.categorical_crossentropy,
metrics=['accuracy'])
fit()で学習実行。これも一緒だね。
# 学習
batch_size = 128 # バッチサイズ
epochs = 10 # エポック
history = model.fit(X_train, y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_data=(X_test, y_test))
最後は検証データで、モデルを評価。
# モデル評価
score = model.evaluate(X_test, y_test, verbose=0)
print('Test loss:', np.round(score[0], 4))
print('Test accuracy:', score[1])
正答率は約99%。学習履歴もプロットしておく。
# モデル学習履歴をグラフで可視化
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()
今回の畳み込みを使ったディープラーニングの練習は以上で。
お疲れ様でした。またね!
0 件のコメント :
コメントを投稿