Flickr APiで取得した画像データをCNNを利用して判定

hanamichi-sukusuku.hatenablog.com

今回は上記でnumpy形式に変換したFlickr APIで取得した画像データを使って、CNNで機械学習にかけていく。

 

モデルを別ファイルに定義

 cnn_model.py

f:id:hanamichi_sukusuku:20210226165527p:plain

モデルでは畳み込み、畳み込み、プーリング、ドロップアウト、この流れを2回繰り返し、Flatten()で平滑化、全結合層へと流し込んでいくように定義。

 

get_model()関数ではdef_model()関数を呼び出しモデルを取得。

そして、モデルを構築し呼び出し元に返す。

 

次にnumpy形式に変換したFlickr APIの画像データを作成したモデルを用いて学習させていく

f:id:hanamichi_sukusuku:20210226170505p:plain

f:id:hanamichi_sukusuku:20210226170629p:plain

実行結果

f:id:hanamichi_sukusuku:20210226170721p:plain

f:id:hanamichi_sukusuku:20210226171045p:plain

実行結果としてはそこまでいい正解率ではなかった。画像クリーニングでの精査をしっかりすればもう少し上がる気がする。

 

プログラムを見ていく

入力出力の変数を定義

im_rows = 32 # 画像の縦ピクセルサイズ
im_cols = 32 # 画像の横ピクセルサイズ
im_color = 3 # 画像の色空間
in_shape = (im_rows, im_cols, im_color)
nb_classes = 3

画像サイズは縦、横32ピクセルなので32をそれぞれ定義。

今回扱う画像の色空間はRGBなのでim_colorには3を定義。

in_shapeには入力レイヤーに渡す入力を定義。CNNなので3次元の入力数を定義。

nd_classesには出力数を指定。sushi、salad、tofuの3種類なので3。

 

画像データの読み込み

photos = np.load('image/photos.npz')
x = photos['x']
y = photos['y']

 

作成したnumpy形式のデータはimageディレクトリにphotos.npzというファイル名で保存されているのでそれを読み込む。

photos['x']、photos['y']でx(画像データ)、y(ラベルデータ)を取得しているのは、保存する際のnp.savez()でそれぞれの配列名をx,yとして保存したため、オブジェクトからの取得の仕方が['x']、['y']のようになる。

 

データをCNNで学習できるように変換、テスト用、学習用に分割

x = x.reshape(-1, im_rows, im_cols, im_color)
x = x.astype('float32') / 255
# ラベルデータをone-hotベクトルに直す --- (*4)
y = keras.utils.to_categorical(y.astype('int32'), nb_classes)

# 学習用とテスト用に分ける --- (*5)
x_train, x_test, y_train, y_test = train_test_split(
   x, y, train_size=0.8)

reshapeで三次元の配列に変換、astypeでデータ型の変換と255で割ることでデータを0.0~1.0で表現できるようにしている。

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

train_test_split()でテスト用、学習用に変換。

 

先ほど作成したCNNモデルを定義したファイルからモデルを読み込み、学習させる

model = cnn_model.get_model(in_shape, nb_classes)

# 学習を実行 --- (*7)
hist = model.fit(x_train, y_train,
   batch_size=32,
   epochs=20,
   verbose=1,
   validation_data=(x_test, y_test))

 

cnn_model.get_model(in_shape, nb_classes)では上記で作成したcnn_model.pyからget_model関数を実行している。これによってCNNモデルを取得できる。

 

model.fit()で学習。validation_dataで学習とともにテストデータの評価結果を変数histに格納。

 

モデル評価と結果出力

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

model.evaluate()でテストデータの評価。

 

学習の様子をグラフに描画

# 正解率の推移をプロット
plt.plot(hist.history['accuracy'])
plt.plot(hist.history['val_accuracy'])
plt.title('Accuracy')
plt.legend(['train', 'test'], loc='upper left')
plt.show()

# ロスの推移をプロット
plt.plot(hist.history['loss'])
plt.plot(hist.history['val_loss'])
plt.title('Loss')
plt.legend(['train', 'test'], loc='upper left')
plt.show()

model.save_weights('./image/photos-model-light.hdf5')

 

historyオブジェクトが格納されている変数histから正解率、ロス、それぞれのデータを取得しグラフに描画。

最後にmodel.save_weights()でモデルの重みデータを保存。