CNNを利用して作成した重みデータを保存し、そのデータで画像の判定


from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D
import matplotlib.pyplot as plt


im_size = 32 * 32 *3
num_classes = 10
im_rows = 32
im_cols = 32
in_shape = (im_rows, im_cols, 3)

model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same',
input_shape=in_shape))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes))
model.add(Activation('softmax'))

# モデルをコンパイル --- (*4)
model.compile(
  loss='categorical_crossentropy',
  optimizer='adam',
  metrics=['accuracy'])

 

model.load_weights('cifar10-weight.h5')

import cv2
import numpy as np

labels = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"]

 

im = cv2.imread('test-car.jpg')

im=cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
im = cv2.resize(im, (32, 32))
plt.imshow(im)
plt.show()

im = im.astype('float32') / 255

r = model.predict(np.array([im]), batch_size=32, verbose=1)
res = r[0]
for i, acc in enumerate(res):
 print(labels[i], "=", int(acc * 100))

print("-----")
print("予測した結果=", labels[res.argmax()])

 

実行結果

f:id:hanamichi_sukusuku:20210211152041p:plain

hanamichi-sukusuku.hatenablog.com

今回使用する重みデータは上記で作成したもの。

モデルにパラメーターを渡してからが重要なのでここでのモデル構築に関しては割愛する。

model.load_weights('cifar10-weight.h5')

import cv2
import numpy as np

labels = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"]

 

im = cv2.imread('test-car.jpg')

im=cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
im = cv2.resize(im, (32, 32))
plt.imshow(im)
plt.show()

im = im.astype('float32') / 255

r = model.predict(np.array([im]), batch_size=32, verbose=1)
res = r[0]
for i, acc in enumerate(res):
 print(labels[i], "=", int(acc * 100))

print("-----")
print("予測した結果=", labels[res.argmax()])

 

この部分のプログラムをみていく。

 

重みデータ読み込み

model.load_weights()で保存してある重みデータのファイル名を指定し読み込む。

 

画像の読み込みと表示

画像の読み込みにopencvを利用。

imread()で画像を読み込み、cvtColor()でRGB色空間に変換、今回のモデルでは32✖️32ピクセルの画像を処理できるようになっているのでresize()で32✖️32の画像に変換。

 

画像データの正規化

im = im.astype('float32') / 255で0.0~1.0で表現するように変換する。今回はCNNでの判定なので三次元のデータのまま使用できる。もし、MLPアルゴリズムを使用するならここで一次元の配列にする必要がある。

 

結果の予測

model.predict()で画像データを予測。

変数rには最終的なクラス数である10個の配列になっている。

f:id:hanamichi_sukusuku:20210211160025p:plain

出力すると上記のような中身になっている。

 

それぞれのラベルの予測結果を表示

res = r[0]
for i, acc in enumerate(res):
 print(labels[i], "=", int(acc * 100))

予測結果は二次元の配列になっているのでres = r[0]

 

enumerate()を使用するとインデックス番号と要素をそれぞれ取得できる。

返り値は(インデックス番号, 要素)。つまりfor文のiにインデックス、accに要素が入る。

ラベルごとに100をかけた値を出力。

実行結果でほとんどが0なのはint()を使用した時に端数は切り捨てられるから。

予測結果の中身をみると5.5786779e-14など見慣れないものがあるがこれは

5.5786779✖️0.00000000000001のことで計算を行うと1.0未満になるためint()で処理すると0になる。

2.34e+4なら2.34✖️10000、2.34e-4なら2.34✖️0.0001を意味する。

 

配列から最大値を取得し、そのラベルを出力

print("予測した結果=", labels[res.argmax()])

argmax()で配列から最大の値を持つインデックス番号を取得。

labelsの中からそれに対応した値を取得し出力すると予測結果のラベルがわかる。