カタカナ画像のデータを簡単なニューラルネットワークで分類

f:id:hanamichi_sukusuku:20210214211038p:plain

実行結果

f:id:hanamichi_sukusuku:20210214211600p:plain

比較的高い結果を得ることができた。

必要な値の定義、画像データ読み込み

import numpy as np
import cv2, pickle
from sklearn.model_selection import train_test_split
import keras

# データファイルと画像サイズの指定 --- (*1)
data_file = "./png-etl1/katakana.pickle"
im_size = 25
in_size = im_size * im_size
out_size = 46 # ア-ンまでの文字の数

# 保存した画像データ一覧を読み込む --- (*2)
data = pickle.load(open(data_file, "rb"))

hanamichi-sukusuku.hatenablog.com

上記で保存したカタカナ画像データをpickle.load()で読み込む。

out_sizeはア~ンまでの文字の個数。最終的に判定したいクラス数を定義。

im_size,in_sizeは画像データのサイズが25✖️25なのでそのサイズを定義。

 

画像を0~1の範囲の直し、x,yのデータを作成

y =
x =
for d in data:
(num, img) = d
img = img.reshape(-1).astype('float') / 255
y.append(keras.utils.to_categorical(num, out_size))
x.append(img)
x = np.array(x)
y = np.array(y)

画像データを読み込んだdataには画像データとそれに対応したラベルデータが格納されているので、num, imgでそれぞれ分けている。imgに格納された画像データをreshape()で一次元にし、astype()でデータ型変換。255で割ることで0.0~1.0で表現するようにしている。

ラベルデータはkeras.utils.to_categorical()で46クラスで表現したラベルデータに変換しone-hotベクトルにする。

 

学習用とテスト用に分割

x_train, x_test, y_train, y_test = train_test_split(
   x, y, test_size = 0.2, train_size = 0.8, shuffle = True)

 

モデル定義

Dense = keras.layers.Dense
model = keras.models.Sequential()
model.add(Dense(512, activation='relu', input_shape=(in_size,)))
model.add(Dense(out_size, activation='softmax'))

このモデルでは一次元の配列を使用するので25✖️25の値が格納されているin_sizeをinput_shape()に渡す。

 

出力レイヤーのout_sizeは46種類の結果が存在するのでその値の46を指定。

 

モデルのコンパイルと学習

model.compile(
  loss='categorical_crossentropy',
  optimizer='adam',
  metrics=['accuracy'])
model.fit(x_train, y_train,
  batch_size=20, epochs=50, verbose=1,
  validation_data=(x_test, y_test))

 

モデル評価

score = model.evaluate(x_test, y_test, verbose=1)
print('正解率=', score[1], 'loss=', score[0])