buto > /dev/null

だいたい急に挑戦してゴールにたどり着かずに飽きる日々です

画像分類 画像をグレースケールにするわけ

Kerasで定番のMNISTをやりました

ディープラーニングやってみたいな~と思い、実践系のテキストを買ってテキストを写経コーディング ちゃんと学習した実行結果が得られたが、コードの意味を一行ずつ理解するのに時間が掛かる…

MNISTはこんな手書き数字の画像

f:id:butorisa:20201020165323p:plain

テキスト:Kerasによるディープラーニング:実践テクニック&チューニング技法

データ前処理で画像を255で割るのはなんで?

Kerasを使ってMNIST手書き数字画像を「0~9のクラスに分類」するコードの前処理 1. MNISTデータをダウンロードするmnist.load_data() 1. 学習データ、テストデータの画像をそれぞれreshapeする → 1枚の画像が一次元配列になる(全結合層に投入する準備) 1. 配列をfloat32型にして、255で割る(なんで??)

# ???何してるんだ???
num_gray_scale_max = 255
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')

x_train /= num_gray_scale_max
x_test /= num_gray_scale_max

RGB値を255で割って画像を正規化している

画像のピクセル値を255で割って「0~1」の間の数値に正規化する → グレースケールにしている

グレースケール画像はカラー画像より計算効率が高いということなので、 正規化すると学習予測がきちんとできる

正規化 VS 非正規化

正規化した画像データと、正規化していない画像データで学習予測(分類)してみた!

正規化した時

f:id:butorisa:20201020165350p:plain

正規化していない時

f:id:butorisa:20201020165423p:plain

正規化していない時はガッタガタ。。。なぜか学習よりテストのほうが正解率が高い

import numpy as np
import keras
from keras.datasets import mnist
import pickle
from matplotlib import pyplot as plt
%matplotlib inline

# MNISTデータセット読み込み
# (学習画像,学習ラベル),(テスト画像,テストラベル)
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# 行数を保存
num_train_data = x_train.shape[0]
num_test_data = x_test.shape[0]

# 画像の行と列を掛け算して一次元配列にする時の要素数を求める
# 28×28なので784
num_flatten_data = x_train.shape[1] * x_train.shape[2]

# 画像データを行列に変換
x_train = x_train.reshape(num_train_data, num_flatten_data)
x_test = x_test.reshape(num_test_data, num_flatten_data)

# 画像データを0~1に正規化
num_gray_scale_max = 255
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')

x_train /= num_gray_scale_max
x_test /= num_gray_scale_max

num_classes = 10
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop

model = Sequential()
# ノード512個、活性化関数ReLU、入力値は一次配列で784要素(28×28)
model.add(Dense(512, activation='relu', input_shape=(784,)))
# 20%の学習データを間引く
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
# 0~9の10クラス分類
model.add(Dense(10, activation='softmax'))
model.summary()
model.compile(loss='categorical_crossentropy', optimizer='RMSprop', metrics=['accuracy'])

batch_size = 128
epochs = 50

# 学習画像、学習ラベル、バッチサイズ、エポック数、進捗を表示、テストデータ
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test,y_test))

# 重みをpickleファイルに保存
with open('./weight_keras_mnist.pkl', 'wb') as h_file:
    pickle.dump(history.history, h_file)

# 学習結果をグラフにする
plt.figure(figsize=(10,6))

plt.plot(history.history['accuracy'], color='b')
plt.plot(history.history['val_accuracy'], color='r')

plt.tick_params(labelsize=18)
plt.title('epoch - accuracy graph')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train','test'])
plt.show()