CNNの転移学習【図解速習DEEP LEARNING】#005
こんにちは!こーたろーです。
今日も図解速習DEEP LEARNINGの続きをやっていきます!
今回の実践では、事前学習済みのモデルと、その転移学習(ファインチューニング)を使って、犬猫画像の分類を行いました。
長くなったため、ブログのパートを二つに分けます。
学習済みモデルをカスタマイズして使う方法として、
- 学習済みモデルを特徴抽出に使う
- 学習済みモデルのファインチューニング
の二通りをやってみます。
今回は「1.学習済みモデルを特徴抽出に使う」方法を試してみました。
1.必要なライブラリーのインストール・インポート
import os import tensorflow as tf from tensorflow import keras import numpy as np import matplotlib.pyplot as plt
2.データセットの準備
try: import tensorflow_datasets as tfds except: !python -m pip install tensorflow-datasets import tensorflow_datasets as tfds tfds.disable_progress_bar()
Google Colabratoryには、Tensorflow_datasetsが予めインストールさせていないことがあるため、Try-Except文で、読み込ませる。
「!」を構文の頭に入れることによって、ターミナルと同様にpipコマンドが扱えます。
(raw_train, raw_validation, raw_test), metadata = tfds.load( 'cats_vs_dogs', split=['train[:80%]', 'train[80%:90%]', 'train[90%:]'], with_info=True, as_supervised=True, )
splitを使用し、データを学習データ80%、検証データ10%、テストデータ10%として、データセットを分割します。
データセットの中身を確認してみましょう。
get_label_name = metadata.features['label'].int2str for image, label in raw_train.take(2): plt.figure() plt.imshow(image) plt.title(get_label_name(label))
out
画像サイズも160×160とし、ピクセルの値(0-255)を-1~1の値に変更していきます。
IMG_SIZE = 160 def format_example(image, label): image = tf.cast(image, tf.float32) image = (image/127.5) - 1 image = tf.image.resize(image, (IMG_SIZE, IMG_SIZE)) return image, label
上記のような関数を全てのピクセルに適用させるため、map( )を使用します。
「train」「validation」「test」のデータセット各々を処理していきます。
train = raw_train.map(format_example) validation = raw_validation.map(format_example) test = raw_test.map(format_example)
データセットをシャッフルして、バッチにまとめていきます。
BATCH_SIZE = 32 SHUFFLE_BUFFER_SIZE = 1000
train_batches = train.shuffle(SHUFFLE_BUFFER_SIZE).batch(BATCH_SIZE) validation_batches = validation.batch(BATCH_SIZE) test_batches = test.batch(BATCH_SIZE)
3.モデルの作成
Googleが開発したMobileNetV2からモデルを作成します。
ImageNetで学習済みの重み(weight=’imagenet’)をMobileNetV2でモデルとして呼び出し、特徴抽出を行います。
この時、Include_top=False引数をしていすることで、一番上の分類レイヤ(最終層)を除いたモデルが読み込まれます。
特徴抽出においては、この最終層は分類においてはあまり役に立たないため、除いて読み込むことをお勧めします。
IMG_SHAPE = (IMG_SIZE, IMG_SIZE, 3) base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE, include_top=False, weights='imagenet')
この特徴抽出は、160×160×3の画像から、5×5×1280の特徴マップを取り出します。
特徴を抽出したレイヤーの重みが更新されないように設定する。
base_model.trainable = False
特徴ブロックから予測を生成するため、tf.keras.layers.GlobalAveragePooling2D層をつかって、5×5ごとに平均化とプーリングを行い、特徴を1画像あたり1280要素をもつ1次元ベクトルに変換していきます。
global_average_layer = tf.keras.layers.GlobalAveragePooling2D()
feature_batch_average = global_average_layer(feature_batch)
print(feature_batch_average.shape)
予測を出力するための層を作成します。正=1、負=0として、出力するように設定します。
prediction_layer = keras.layers.Dense(1) prediction_batch = prediction_layer(feature_batch_average) print(prediction_batch.shape)
out
kerasのSequentialで各層を連結していきます。
model = tf.keras.Sequential([ base_model, global_average_layer, prediction_layer ])
4.モデルのコンパイル
2クラス分類のため、バイナリクロスエントロピー損失を使いました。
base_learning_rate = 0.0001 model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=base_learning_rate), loss='binary_crossentropy', metrics=['accuracy'])
できたモデルを見てみましょう。
model.summary()
out
len(model.trainable_variables)
最終のDense送の1281のパラメータは、固定されていないため、学習の余地があります。
そこで、モデルを学習させていきます。
5.モデルの学習
initial_epochs = 10 validation_steps = 20 loss0,accuracy0 = model.evaluate(validation_batches, steps = validation_steps)
out
損失・正解率を確認
print("initial loss: {:.2f}".format(loss0)) print("initial accuracy: {:.2f}".format(accuracy0))
out
history = model.fit(train_batches, epochs=initial_epochs, validation_data=validation_batches)
out
6.学習結果の表示
acc = history.history['accuracy'] val_acc = history.history['val_accuracy'] loss = history.history['loss'] val_loss = history.history['val_loss'] plt.figure(figsize=(8, 8)) plt.subplot(2, 1, 1) plt.plot(acc, label='Training Accuracy') plt.plot(val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.ylabel('Accuracy') plt.ylim([min(plt.ylim()),1]) plt.title('Training and Validation Accuracy') plt.subplot(2, 1, 2) plt.plot(loss, label='Training Loss') plt.plot(val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.ylabel('Cross Entropy') plt.ylim([0,1.0]) plt.title('Training and Validation Loss') plt.xlabel('epoch') plt.show()
out
とりあえず今日はここまでできました。
次は、学習済みモデルのファインチューニング
今日のまとめ。
学習が完了している層をもってきて、そこにCNNらしくプーリング層、それから予測用の層を追加。
追加した層の重みだけを学習で更新させて、学習済みの層と併せてモデルを構築。