Pythonとtensorflow.kerasを使ってMNISTの手書き文字認識をやる方法

スポンサーリンク

学習者の本日のチュートリアルでは、sklearn のデータセットにある MNIST データセットから、手書きの数字を認識する方法を学びます。

数字を認識するために、CNN(Convolutional Neural Networks)を使用します。

まず、CNNが何であるかを理解することから始めましょう。

スポンサーリンク

畳み込みニューラルネットワークとは?

CNNは、多層パーセプトロンに基づく計算タスクのための最も重要なニューラルネットワークモデルの1つです。

これらのモデルは、画像の処理に特に優れた性能を発揮します。

例えば、手書きの認識。

手書き文字認識は、ニューラルネットワークの最も基本的で優れた用途の1つです。

畳み込みニューラルネットワークの使用例

CNNは画像処理などの分野で重要な役割を担っている。

検出や予測に強力なインパクトを与えています。

半導体の製造のようなナノテクノロジーでも使われている。

ここでは、材料の欠陥を検出するために使用されています。

CNNをKerasやTensorflowと一緒に使えば、様々な分類アルゴリズムと比較して最高の精度を得ることができる。

CNNとバックプロパゲーションアーキテクチャを組み合わせると、MNISTデータセットで、他のどのデータセットよりも高い精度が得られる。

CNNを用いた新しいアプリケーションは、研究によって日々開発されている。

ドイツでは、CNNを用いた交通標識認識モデルが提案されている。

手書き文字認識用データセットの読み込みと準備

今回使用するデータセットには、約6万枚のトレーニング画像と約1万枚のテスト画像が含まれています。

そして、このデータをトレーニング用とテスト用のデータセットにそれぞれ分割します。

x_trainx_testには画像のピクセルコードが、y_testy_train`には0から9の数字を表すラベルが格納されています。

ここで、データセットの形状がCNNモデルで使用するのに適しているかどうかを確認する必要があります。

データサイズは(60000,28,28)となっており、28×28ピクセルの画像が60000枚あることになります。

しかし、Keras APIを使用するためには4次元配列のデータセットが必要なので、3次元データを4次元データセットに変換する必要があります。

1
2
3
4
5
6
import tensorflow as tf
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
 
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
x_test = x_test.reshape(x_test.shape[0], 28, 28, 1)
input_shape = (28, 28, 1)

次に、データの正規化を行います。

まず、データをfloatに変換し、255(RGBコードの最大値-RGBコードの最小値)で割って正規化します。

1
2
3
4
5
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
 
x_train /= 255
x_test /= 255

モデルの構築

この記事では、Keras APIを使用してモデルを構築します。

そのために、KerasからSequential Modelをインポートして、以下のような複数のレイヤーを追加します。

  1. Conv2D
  2. MaxPooling
  3. 平坦化
  4. ドロップアウト

Dropout層はオーバーフィッティングを抑制し、Flatten層は2次元配列を1次元配列に平坦化します。

1
2
3
4
5
6
7
8
9
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, Dropout, Flatten, MaxPooling2D
model = Sequential()
model.add(Conv2D(28, kernel_size=(3,3), input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(128, activation=tf.nn.relu))
model.add(Dropout(0.2))
model.add(Dense(10,activation=tf.nn.softmax))

モデルのコンパイルとフィッティング

さて、これで最適化されていない空のCNNを作成しました。

次に、あるメトリックを利用した損失関数でオプティマイザを設定し、作成した訓練データセットを用いてモデルを適合させます。

ADAMオプティマイザは、他の類似のオプティマイザよりも優れています。

1
2
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(x=x_train,y=y_train, epochs=10)

学習過程の結果は以下の通りです。

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
import matplotlib.pyplot as plt
plt.style.use('seaborn')
 
plt.figure(figsize=(10,10))
plt.subplot(4,4,1)
image_index = 2853
predict = x_test[image_index].reshape(28,28)
pred = model.predict(x_test[image_index].reshape(1, 28, 28, 1))
plt.imshow(x_test[image_index].reshape(28, 28),cmap='Greys')
plt.title("Predicted Label: "+str(pred.argmax()))
 
plt.subplot(4,4,2)
image_index = 2000
predict = x_test[image_index].reshape(28,28)
pred = model.predict(x_test[image_index].reshape(1, 28, 28, 1))
plt.imshow(x_test[image_index].reshape(28, 28),cmap='Greys')
plt.title("Predicted Label: "+str(pred.argmax()))
 
plt.subplot(4,4,3)
image_index = 1500
predict = x_test[image_index].reshape(28,28)
pred = model.predict(x_test[image_index].reshape(1, 28, 28, 1))
plt.imshow(x_test[image_index].reshape(28, 28),cmap='Greys')
plt.title("Predicted Label: "+str(pred.argmax()))
 
plt.subplot(4,4,4)
image_index = 1345
predict = x_test[image_index].reshape(28,28)
pred = model.predict(x_test[image_index].reshape(1, 28, 28, 1))
plt.imshow(x_test[image_index].reshape(28, 28),cmap='Greys')
plt.title("Predicted Label: "+str(pred.argmax()))

evaluate`関数を用いてモデルを評価したところ、98.4%の精度を確認することができました。

結果を可視化する

最後のステップは、学習したモデルの結果を可視化し、subplotsを使ってそれらをプロットすることです。

以下はそのコードと出力です。

結果はかなり正確であることがわかります。

Training Result Handwritten Digit Recog
Training Result Handwritten Digit Recog
Handwritten Digit Recog Output
Handwritten Digit Recog Output

まとめ

この記事では、CNNを統合した手書き数字認識モデルを作成しました。

そして、その精度はかなり良いものでした。

お読みいただきありがとうございました。

タイトルとURLをコピーしました