顔写真からジャニーズ系かEXILE系かを判定する学習モデルを作成してみました。
全3回の記事の予定です。
本記事は、 「データの前処理」から「テスト・評価」 (記事 2/3)を掲載しています。
目次
はじめに
Udemyの機械学習講座を受講し終わったので、成果物として作ってみました。
詳細なソースコードはGitHubに上げていますので、よろしければそちらを参照ください。
また、画像のクローリング・顔検出処理の詳細は以前書いたこちらの記事を参考ください。
動作環境
・Anaconda 3
・TensorFlow (CPU版)
全体の処理フロー
全体の処理フローを下図に記します。
本記事では、「データの前処理」から「テスト・評価」について説明していきます。
データの前処理
収集した教師データの画像をTensorFlowが扱いやすい形(NumPy配列形式)に変換していきます。
そして変換されたNumPyファイルを出力します。
また、その際にscikit-learnを使って学習用と評価用のデータに分けてあげます。
また、その際にscikit-learnを使って学習用と評価用のデータに分けてあげます。
モデルの定義
今回は深層学習ライブラリであるKerasを使ってモデルを定義してみました。
とりあえず複雑なことはせずに、Kerasの公式ドキュメンテーションを参考にニューラルネットワークを作ってみました。
今回は「ジャニーズ系」か「EXILE系」かの2クラスの画像分類問題ですので、出力層はノードが2つになります。
ソースコードはこちら。
from keras.models import Sequential from keras.layers import Conv2D, MaxPooling2D from keras.layers import Activation, Dropout, Flatten, Dense from keras.utils import np_utils import keras import numpy as np classes = ["exile", "jonnys"] num_classes = len(classes) image_size = 50 # メイン関数の定義 def main(): x_train, x_test, y_train, y_test = np.load("judge_exile_johnnys.npy") # データの正規化 x_train = x_train.astype("float") / 256 x_test = x_test.astype("float") / 256 # ラベルのone-hot-vector(正解は1, 他は0となるような処理) y_train = np_utils.to_categorical(y_train, num_classes) y_test = np_utils.to_categorical(y_test, num_classes) # モデルの生成 model = model_train(x_train, y_train) # モデルの評価 model_eval(model, x_test, y_test) def model_train(x, y): #層の定義 model = Sequential() model.add(Conv2D(32,(3,3), padding='same', input_shape=x.shape[1:])) 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(2))#クラスの数(今回は画像のクラスが2つ) model.add(Activation('softmax')) # 最適化の定義 opt = keras.optimizers.rmsprop(lr=0.0001, decay=1e-6) model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy']) model.fit(x, y, batch_size=32, epochs=25) # モデルの保存 model.save('./exile_johnnys_cnn.h5') return model def model_eval(model, x, y): scores = model.evaluate(x, y, verbose=1) print('Test Loss: ', scores[0]) print('Test Accuracy: ', scores[1]) if __name__ == "__main__": main()
トレーニング(教師あり学習)
作成したモデルを使って学習してみます。
結果がこちら。
結果
・トレーニング画像のAccracy: 82%
・テスト画像のAccruacy: 71%
パラメータチューニングも教師データの水増しもやっていないので、
こんなものかなって感じです。
テスト・評価
精度は大して良くないモデルですが、これを使っていくつか画像分類してみました。
評価に使った画像は未学習のグループにしました。
評価に用いたソースコードはこちら。
from keras.models import Sequential, load_model from keras.layers import Conv2D, MaxPooling2D from keras.layers import Activation, Dropout, Flatten, Dense from keras.utils import np_utils import keras, sys import numpy as np from PIL import Image classes = ["exile", "jonnys"] num_classes = len(classes) image_size = 50 def build_model(): #層の定義 model = Sequential() model.add(Conv2D(32,(3,3), padding='same', input_shape=(50,50,3))) 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(2))#クラスの数(今回は画像のクラスが2つ) model.add(Activation('softmax')) # 最適化の定義 opt = keras.optimizers.rmsprop(lr=0.0001, decay=1e-6) model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy']) # モデルのロード model = load_model("./exile_johnnys_cnn.h5") return model def main(): image = Image.open(sys.argv[1]) image = image.convert('RGB') image = image.resize((image_size,image_size)) data = np.asarray(image) X = [] X.append(data) X = np.array(X) model = build_model() result = model.predict([X])[0] predicted = result.argmax() percentage = int(result[predicted] * 100) print("{0} ({1} %)".format(classes[predicted], percentage)) if __name__ == "__main__": main()
・EXILEグループのメンバーはどう分類されたのか?
使った画像は「THE RAMPAGE LIKIYA」さんです。
見事に正解しました。
・ジャニーズグループのメンバーはどう分類されたのか?
使った画像は「NEWS 手越祐也」さんです。
分類に失敗して、EXILE系に分類されてしまいました。。
今回はニューラルネットワークのパラメータチューニングや教師データの水増しもやっていませんでしたが、
次回はこれらを実践してみて、どの程度精度があがるかを検証してみたいと思います。
次回はこれらを実践してみて、どの程度精度があがるかを検証してみたいと思います。
参考
・顔写真から、乃木坂46系かAKB48系か一般人系か判定する学習モデル作ってみた
・Keras公式ドキュメンテーション
スポンサーリンク