nprogram’s blog

気ままに、プログラミングのトピックについて書いていきます

mnist手書き数字画像データ学習モデル活用でjpeg画像を予測します [Python]

はじめに

手書き文字の認識をNeuralnetworkを用いて行います。 Kerasから手書き文字のデータをダウンロードして、そのデータを用いて、NeuralnetworkのTrainingを行い、その後に下記のnumber_fileをTest dataとして数字の認識を実施します。

コード例

from keras import backend as K
from keras.datasets import mnist
from keras.layers import Activation, Dense, Dropout
from keras.layers.normalization import BatchNormalization
from keras.models import Sequential
from keras.utils.np_utils import to_categorical
import numpy as np
from sklearn.metrics import classification_report, confusion_matrix

# Kerasに付属の手書き数字画像データをダウンロード
np.random.seed(0)
(X_train, labels_train), (X_test, labels_test) = mnist.load_data()

# Traning setのラベルを確認
labels_train

# Training setの概要確認
print(X_train.shape, labels_train.shape, sep='\n')

# Test setの概要確認
print(X_test.shape, labels_test.shape, sep='\n')

# Training setの画像を表示
import matplotlib.pyplot as plt
%matplotlib inline

label_images = {label: [] for label in set(labels_train.tolist())}
for x, label in zip(X_train, labels_train):
    if all(len(images) >= 10 for images in label_images.values()):
        break
    if len(label_images[label]) >= 10:
        continue
    label_images[label].append(x)
    
for j, (label, images) in enumerate(label_images.items()):
    plt.subplot(10, 11, j * 11 + 1)
    plt.text(0.5, 0.5, label, ha='center', va='center')
    plt.axis('off')
    for i, image in enumerate(images):
        if i >= 10:
            continue
        plt.subplot(10, 11, j * 11 +  i + 2)
        plt.imshow(image, cmap='Greys_r')
        plt.axis('off')
plt.show()
    
del label_images

# Test dataの画像表示

label_images = {label: [] for label in set(labels_test.tolist())}
for x, label in zip(X_test, labels_test):
    if all(len(images) >= 10 for images in label_images.values()):
        break
    if len(label_images[label]) >= 10:
        continue
    label_images[label].append(x)
    
for j, (label, images) in enumerate(label_images.items()):
    plt.subplot(10, 11, j * 11 + 1)
    plt.text(0.5, 0.5, label, ha='center', va='center')
    plt.axis('off')
    for i, image in enumerate(images):
        if i >= 10:
            continue
        plt.subplot(10, 11, j * 11 +  i + 2)
        plt.imshow(image, cmap='Greys_r')
        plt.axis('off')
plt.show()
    
del label_images


##  画像データを特微ベクトルに変換します

# 各画像は行列なのでベクトルに変換→X_trainとX_testを作成
X_train = X_train.reshape(len(X_train), -1)
X_test = X_test.reshape(len(X_test), -1)

print(X_train.shape)
print(X_train[:5])

# ラベルをone-hotベクトル(値がひとつだけ1で他が0のベクトル)に変換→Y_trainとY_testを作成
Y_train = to_categorical(labels_train)
Y_test = to_categorical(labels_test)

print(Y_train)

print(Y_test)

##  Deep learningの実施

# モデルの準備
model = Sequential()
model.add(Dense(10, input_shape=(784,)))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

# Trainingの実施
model.fit(X_train, Y_train, batch_size=128, nb_epoch=10, verbose=1)

# Test dataを用いてモデルを評価(accuracyを算出)
_, acc = model.evaluate(X_test, Y_test, verbose=0)
print('accuracy: {}'.format(acc))

# Classification_report関数で評価結果を表示
labels_pred = model.predict_classes(X_test, verbose=0)
print(confusion_matrix(labels_test, labels_pred))
print(classification_report(labels_test, labels_pred))

# Training後のモデルを用いてnumber_file中の画像の数字を予測

# 必要なモジュールの読み込み
import glob
import os
from PIL import Image

(x_train, y_train), (x_test, y_test) = mnist.load_data()

print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)

img_dir = 'number_file'
os.makedirs(img_dir, exist_ok=True)

# 全画像分を保存するようにする
for data, label in zip(x_test[:1000], y_test[:1000]):
    img = Image.fromarray(data)
    # グレースケール形式で保存する。
    img.save(os.path.join(img_dir,
             'gray_{}.png'.format(label)))

    # RGB 形式で保存する。
    img = img.convert('RGB')
    img.save(os.path.join(img_dir,
             'color_{}.png'.format(label)))

# フォルダ内の画像を読み込み、予測する。
for img_path in glob.glob(os.path.join(img_dir, '*.png')):
    # 画像を読み込む。
    img = Image.open(img_path)

    # 画像が RGB ならグレースケールに変換する。(28, 28, 3) -> (28, 28)
    if img.mode == 'RGB':
        img = img.convert("L")
    # 行列を1次元に変換する(28, 28) -> (1, 784) にする。
    data = np.array(img).reshape(1, -1)

    # データをモデルに入れて予測
    pred_y = model.predict_classes(data, verbose=0)
    print(img_path, pred_y)

主な出力イメージ

accuracy: 0.9061

[[ 961    0    2    3    0    3    8    1    2    0]
 [   0 1091   25    3    1    1    3    2    9    0]
 [   3    0  967    5   16    3    7    9   19    3]
 [   4    0   56  870    4   37    1    8   21    9]
 [   2    1    8    0  933    0    9    2    8   19]
 [  11    1   15   23   24  762   10    6   36    4]
 [  14    1   28    0   12   25  867    1   10    0]
 [   2    5   33    4   15    0    0  943    4   22]
 [   5    3   36   12   20   19    3   16  856    4]
 [   9    4    2    9  109   15    1   33   16  811]]
              precision    recall  f1-score   support

           0       0.95      0.98      0.97       980
           1       0.99      0.96      0.97      1135
           2       0.83      0.94      0.88      1032
           3       0.94      0.86      0.90      1010
           4       0.82      0.95      0.88       982
           5       0.88      0.85      0.87       892
           6       0.95      0.91      0.93       958
           7       0.92      0.92      0.92      1028
           8       0.87      0.88      0.88       974
           9       0.93      0.80      0.86      1009

   micro avg       0.91      0.91      0.91     10000
   macro avg       0.91      0.90      0.91     10000
weighted avg       0.91      0.91      0.91     10000

number_file\color_0.png [0]
number_file\color_1.png [1]
number_file\color_2.png [2]
number_file\color_3.png [3]
number_file\color_4.png [4]
number_file\color_5.png [5]
number_file\color_6.png [6]
number_file\color_7.png [7]
number_file\color_8.png [8]
number_file\color_9.png [9]
number_file\gray_0.png [0]
number_file\gray_1.png [1]
number_file\gray_2.png [2]
number_file\gray_3.png [3]
number_file\gray_4.png [4]
number_file\gray_5.png [5]
number_file\gray_6.png [6]
number_file\gray_7.png [7]
number_file\gray_8.png [8]
number_file\gray_9.png [9]

参考リンク

Python - mnist手書き数字画像データ学習モデル活用でjpeg画像の予測ができません。|teratail

深層学習 TensorFlow を MNIST で試す(2) | ecobioinfo.com – 環境・生物・情報処理 -