【高精度な画像分類器作りに挑戦!】(2)ファインチューニングで高精度化
2018.4.26
こんにちは。データサイエンスチーム tmtkです。
この記事では、桜とコスモスの写真を分類する機械学習モデルを、ファインチューニングを用いて作成します。
はじめに
前回の記事では、畳み込みニューラルネットワークをゼロから作成し、学習させることで、桜とコスモスの写真を分類する機械学習モデルを作成しました。
今回は、ImageNetのために作られたVGG16という畳み込みニューラルネットワークの一部を改変・再学習することで、桜とコスモスの写真を分類する機械学習モデルを作成します。このような方法を、ファインチューニングといいます。
実験
前回の記事と同じ準備の下で実験をします。
IPythonを起動します。
ipython3
まずは、念のため乱数のシードを固定します。
import numpy as np import tensorflow as tf import random as rn import os from keras import backend as K os.environ['PYTHONHASHSEED'] = '0' np.random.seed(0) rn.seed(0) session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1) tf.set_random_seed(0) sess = tf.Session(graph=tf.get_default_graph(), config=session_conf) K.set_session(sess)
次に、画像データを読み込みます。前回と違うところとして、VGG16用の前処理を画像データに施しています。
from keras.preprocessing import image from keras.applications.vgg16 import preprocess_input from sklearn.model_selection import train_test_split import keras import numpy as np import os input_shape = (224, 224, 3) batch_size = 128 epochs = 12 num_classes = 2 x = [] y = [] for f in os.listdir("sakura"): x.append(image.img_to_array(image.load_img("sakura/"+f, target_size=input_shape[:2]))) y.append(0) for f in os.listdir("cosmos"): x.append(image.img_to_array(image.load_img("cosmos/"+f, target_size=input_shape[:2]))) y.append(1) x = np.asarray(x) x = preprocess_input(x) y = np.asarray(y) y = keras.utils.to_categorical(y, num_classes) x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.33, random_state= 3)
VGG16のモデルを最後の全結合層を除いて読み込み、かわりに新しく別の全結合層を付け加えます。VGG16の部分の畳み込み層は再学習しないように設定します。
from keras.models import Sequential, Model from keras.layers import Dense, GlobalAveragePooling2D from keras.applications.vgg16 import VGG16 base_model = VGG16(weights='imagenet', include_top=False) x = base_model.output x = GlobalAveragePooling2D()(x) x = Dense(1024, activation='relu')(x) predictions = Dense(num_classes, activation='softmax')(x) model = Model(inputs=base_model.input, outputs=predictions) for layer in base_model.layers: layer.trainable = False model.compile(loss=keras.losses.categorical_crossentropy, optimizer="rmsprop", metrics=['accuracy'])
自分で付け加えた全結合層の部分を学習させます。
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test, y_test))
以下のように学習が進みます。
Train on 20 samples, validate on 10 samples Epoch 1/12 20/20 [==============================] - 4s 204ms/step - loss: 1.5333 - acc: 0.4500 - val_loss: 7.4123 - val_acc: 0.5000 Epoch 2/12 20/20 [==============================] - 0s 20ms/step - loss: 6.3482 - acc: 0.5000 - val_loss: 0.9846 - val_acc: 0.8000 Epoch 3/12 20/20 [==============================] - 0s 20ms/step - loss: 0.0029 - acc: 1.0000 - val_loss: 0.7341 - val_acc: 0.9000 ... Epoch 10/12 20/20 [==============================] - 0s 20ms/step - loss: 4.4952e-05 - acc: 1.0000 - val_loss: 0.7017 - val_acc: 0.9000 Epoch 11/12 20/20 [==============================] - 0s 21ms/step - loss: 4.1572e-05 - acc: 1.0000 - val_loss: 0.6978 - val_acc: 0.9000 Epoch 12/12 20/20 [==============================] - 0s 20ms/step - loss: 3.8545e-05 - acc: 1.0000 - val_loss: 0.6941 - val_acc: 0.9000
今回は、学習した結果、最終的に訓練データに対する精度が100%、バリデーションデータに対する精度が90%になっています。前回の記事でゼロから学習をしたのとは違い、VGG16というImageNetのために作られた汎用性の高いパラメータとモデルを使うことで、汎化性能と精度を得ることができました。また、学習時間も学習エポック数も前回の1/10程度になり、学習も前回より非常に速く進んでいることがわかります。
(訓練データとバリデーションデータに対する精度の推移)
また、エポック数を増やしてもこれ以上あまり学習は進みませんが、前回とは違って過学習には陥らないことがわかります。
(300エポックまで学習した場合)
まとめ
この記事では、桜とコスモスを分類する畳み込みニューラルネットワークを、VGG16をファインチューニングすることにより作成しました。
前回の記事でゼロから学習したのと比べて、学習も高速に進み、汎化性能も獲得することができました。
次回の記事では、VGG16を活用して、SVMへの転移学習によって機械学習モデルを作成し、100%の精度を達成します。
参考
テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!
Follow @twitterデータ分析と機械学習とソフトウェア開発をしています。 アルゴリズムとデータ構造が好きです。
Recommends
こちらもおすすめ
-
画像の特徴を用いたランク学習の論文紹介
2019.6.28
-
Pythonで実装する画像認識アルゴリズム SLIC 入門
2018.2.13
-
口コミデータを活用したレコメンドシステムの可能性
2017.12.7
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28
AWSの料金が 10 %割引になる!
『AWSの請求代行リセールサービス』
2024.07.16