転移学習を用いた
画像分類
Explore ML
復習: TensorFlowについて説明し合いましょう。
TensorFlowはデータフローと微分可能�プログラミングを提供する�無償のOSSライブラリです。
記号演算ライブラリであり、ニューラルネットワークなどの機械学習�アプリケーションに利用できます。
OSS = Open Source Software �(利用者の目的を問わずソースコードを使用、調査、再利用、�修正、拡張、再配布が可能なソフトウェアの総称である from Wiki)
GDSC Osaka Univ. Edit
本日使用するデータセット
GDSC Osaka Univ. Edit
一般的な機械学習のワークフロー
データ収集
モデルの
訓練と検証
問題定義
予測と評価
ユーザ
転移学習のワークフロー
データ
分析
分類レイヤー
の再学習
予測と評価
事前学習済み
モデルの再利用
事前学習済みモデルとは何でしょうか?
事前学習済みモデルとは、
大規模データセットを用いて,事前に学習したモデルです。
転移学習により、任意のタスクに転用することができます。
Tips:大規模な画像分類タスクを学習したモデルを利用することが多い.
GDSC Osaka Univ. Edit
転移学習の概略図
ソースモデル
大量のデータ
(ソースドメイン)
出力
ラベル
ソースモデル
出力
ラベル
対象データ
(対象のドメイン)
GDSC Osaka Univ. Edit
画像分類プログラムの作成
以後はチュートリアルの補助スライド
(講義では使用しない)
STOP
ライブラリの準備
import matplotlib.pyplot as plt
import numpy as np
import os
import tensorflow as tf
from tensorflow.keras.preprocessing
import image_dataset_from_directory
GDSC Osaka Univ. Edit
データのダウンロード
_URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'
path_to_zip = tf.keras.utils.get_file('cats_and_dogs.zip',
origin=_URL, extract=True)
PATH = os.path.join(os.path.dirname(path_to_zip),
'cats_and_dogs_filtered')
train_dir = os.path.join(PATH, 'train')
validation_dir = os.path.join(PATH, 'validation')
訓練データと検証データのそれぞれ
に対するパスを保存
GDSC Osaka Univ. Edit
フォルダの構成
GDSC Osaka Univ. Original
cats_and_dogs_filtered
train
validation
cats
dogs
PATH
train_dir
cats0.jpg
cats1.jpg
validation_dir
データセットクラスの作成
BATCH_SIZE = 32 # バッチサイズを32とする
IMG_SIZE = (160, 160) # 入力画像のサイズを160x160に変形
train_dataset =
image_dataset_from_directory(train_dir,
shuffle=True,
batch_size=BATCH_SIZE,
image_size=IMG_SIZE)
validation_dataset =
image_dataset_from_directory(validation_dir,
shuffle=True,
batch_size=BATCH_SIZE,
image_size=IMG_SIZE)
IMG_SIZEに
変形した画像を、
バッチサイズ個
ランダムに取り出す
ように指定
GDSC Osaka Univ. Edit
学習データの表示
class_names = train_dataset.class_names
plt.figure(figsize=(10, 10))
for images, labels in train_dataset.take(1):
for i in range(9): # 訓練セットの最初の9枚の画像とラベルを表示
ax = plt.subplot(3, 3, i + 1)
plt.imshow(images[i].numpy().astype("uint8"))
plt.title(class_names[labels[i]])
plt.axis("off")
GDSC Osaka Univ. Edit
[補足] tf.dataモジュール (1/2)
モデルの学習を行う際、データに対して以下の処理が必要となる。
・データのシャッフル
・バッチ化
・データの繰り返し抽出
・高速なバッチ抽出
➡ このような複雑な処理は、tf.data APIを使えば容易に実装できる。
GDSC Osaka Univ. Original
[補足] tf.dataモジュール (2/2)
tf.data.APIの例
tf.data.Dataset.shuffle(buffer_size) : データをシャッフルする。
tf.data.Dataset.batch(batch_size) : バッチごとにデータを取り出す。
tf.data.Dataset.repeat(repeat_num) : データセットを繰り返して取り出す。
➡ 他にも処理を高速化するプリフェッチやデータセットを分割する処理
など、多くの機能を提供する。
GDSC Osaka Univ. Original
テストセットの作成
val_batches =
tf.data.experimental.cardinality(validation_dataset)
test_dataset = validation_dataset.take(val_batches // 5)
validation_dataset = validation_dataset.skip(val_batches // 5)
print('Number of validation batches: %d' %
tf.data.experimental.cardinality(validation_dataset))
print('Number of test batches: %d' %
tf.data.experimental.cardinality(test_dataset))
検証セットで利用可能なデータのサンプル数
を調べ、そのうち 20%をテストセットとして
使用
GDSC Osaka Univ. Edit
tf.dataAPIを用いた実行時間の短縮
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_dataset =
train_dataset.prefetch(buffer_size=AUTOTUNE)
validation_dataset =
validation_dataset.prefetch(buffer_size=AUTOTUNE)
test_dataset =
test_dataset.prefetch(buffer_size=AUTOTUNE)
GPU/TPUで処理している間、CPU上で次に渡すデータを
前もって準備するよう指定
GDSC Osaka Univ. Edit
Data Augmentation (データのかさ増し)
過学習を避け、汎化性能を高めるために、現実的にありうる範囲で� サンプルに変形を加えます。(反転、回転、拡大など)
水平反転
回転
GDSC Osaka Univ. Original
Data Augmentationの適用
data_augmentation = tf.keras.Sequential([
tf.keras.layers.experimental.preprocessing
.RandomFlip('horizontal'), # 水平反転
tf.keras.layers.experimental.preprocessing
.RandomRotation(0.2), # 回転
])
GDSC Osaka Univ. Edit
Data Augmentationを適用したサンプルの確認
for image, _ in train_dataset.take(1):
plt.figure(figsize=(10, 10))
first_image = image[0]
for i in range(9): # 訓練セットの最初の9枚の画像とラベルを表示
ax = plt.subplot(3, 3, i + 1)
augmented_image =
data_augmentation(tf.expand_dims(first_image, 0))
plt.imshow(augmented_image[0] / 255)
plt.axis('off')
GDSC Osaka Univ. Edit
ピクセル値の正規化
preprocess_input =
tf.keras.applications.mobilenet_v2.preprocess_input
モデルに含まれる前処理のメソッドを使用して、ピクセル値を[0, 255]から[-1, 1]に正規化
GDSC Osaka Univ. Edit
事前学習済みモデルの読み込み
# 学習済みMobileNet V2をベースモデルに使用
IMG_SHAPE = IMG_SIZE + (3,)
base_model =
tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
include_top=False,
weights='imagenet')
MobileNet V2
MobileNet V2の詳細
1×1畳み込み層
+
ReLU層
1×1畳み込み層
+
恒等関数層
3×3Dwise層
+
ReLU層
線形
ボトルネック
線形
ボトルネック
MobileNet V2のモジュール
Residual Connection
GDSC Osaka Univ. Original
Residual Connection (残差接続)
GDSC Osaka Univ. Original
x : 入力, H(x) : 出力
F(x) = H(x) - x
F(x) : 出力から入力を引いた「残差」
残差を学習することで、そのブロックは、
「非常に小さな変換」だけを担当できる。
層をより深くすることが可能
ベースモデルの出力を確認
image_batch, label_batch = next(iter(train_dataset))
feature_batch = base_model(image_batch)
print(feature_batch.shape)
(32, 5, 5, 1280)
GDSC Osaka Univ. Edit
base_model.trainable = False
# ベースモデルの構造を確認
base_model.summary()
ベースモデルの重みを固定
出力層の追加
|
|
|
|
|
|
|
|
プーリング層
全結合層
MobileNet V2の出力
最終出力
(Dog or Cat)
GDSC Osaka Univ. Original
出力層の設定 (1/2) - プーリング層
global_average_layer =
tf.keras.layers.GlobalAveragePooling2D()
feature_batch_average =
global_average_layer(feature_batch)
print(feature_batch_average.shape)
(32, 1280)
GDSC Osaka Univ. Edit
GlobalAveragePooling2D:
5×5=25個の特徴を平均化し、
チャネルごとに単一の値に変換
出力層の設定 (2/2) - 全結合層
prediction_layer = tf.keras.layers.Dense(1)
prediction_batch =
prediction_layer(feature_batch_average)
print(prediction_batch.shape)
(32, 1)
GDSC Osaka Univ. Edit
モデルの構築
inputs = tf.keras.Input(shape=(160, 160, 3))
x = data_augmentation(inputs)
x = preprocess_input(x)
x = base_model(x, training=False)
x = global_average_layer(x)
x = tf.keras.layers.Dropout(0.2)(x)
outputs = prediction_layer(x)
model = tf.keras.Model(inputs, outputs)
GDSC Osaka Univ. Edit
モデルのコンパイル
base_learning_rate = 0.0001
model.compile(optimizer=
tf.keras.optimizers.Adam(lr=base_learning_rate),
loss=
tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'])
最適化手法としてAdam、
損失関数としてニ値交差エントロピー誤差
を指定
GDSC Osaka Univ. Edit
モデルの確認
model.summary()
len(model.trainable_variables)
GDSC Osaka Univ. Edit
実行結果
モデルの学習
initial_epochs = 10
loss0, accuracy0 =
model.evaluate(validation_dataset)
print("initial loss: {:.2f}".format(loss0))
print("initial accuracy: {:.2f}".format(accuracy0))
GDSC Osaka Univ. Edit
モデルの学習
history = model.fit(train_dataset,
epochs=initial_epochs,
validation_data=validation_dataset)
GDSC Osaka Univ. Edit
学習曲線の表示
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')
GDSC Osaka Univ. Edit
学習曲線の表示
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()
GDSC Osaka Univ. Edit
Fine Tuning
モデルの学習
base_model.trainable = True
# ベースモデルのレイヤー数を確認
print("Number of layers in the base model: ", len(base_model.layers))
# この層以降でFine-tuning (再学習)を行うように設定
fine_tune_at = 100
# ‘fine_tune_at’で設定した以前の層を再び固定
for layer in base_model.layers[:fine_tune_at]:
layer.trainable = False
モデルのコンパイル
model.compile(loss=
tf.keras.losses.BinaryCrossentropy(from_logits=True),
optimizer =
tf.keras.optimizers.RMSprop(lr=base_learning_rate/10),
metrics=['accuracy'])
損失関数としてニ値交差エントロピー誤差、
最適化手法としてRMSpropを指定
また、モデルがすぐに過学習を起こすのを
防ぐため、ここでは学習係数を小さくする。
GDSC Osaka Univ. Edit
モデルの学習
fine_tune_epochs = 10
total_epochs = initial_epochs + fine_tune_epochs
history_fine = model.fit(train_dataset,
epochs=total_epochs,
initial_epoch=history.epoch[-1],
validation_data=validation_dataset)
GDSC Osaka Univ. Edit
学習曲線の表示 (1/2)
acc += history_fine.history['accuracy']
val_acc += history_fine.history['val_accuracy']
loss += history_fine.history['loss']
val_loss += history_fine.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.ylim([0.8, 1])
plt.plot([initial_epochs-1,initial_epochs-1],
plt.ylim(), label='Start Fine Tuning')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
GDSC Osaka Univ. Edit
学習曲線の表示 (2/2)
plt.subplot(2, 1, 2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.ylim([0, 1.0])
plt.plot([initial_epochs-1,initial_epochs-1],
plt.ylim(), label='Start Fine Tuning')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.xlabel('epoch')
plt.show()
GDSC Osaka Univ. Edit
データの評価と予測
loss, accuracy = model.evaluate(test_dataset)
print('Test accuracy :', accuracy)
データの評価と予測
# テストセットからバッチを取得します。
image_batch, label_batch =
test_dataset.as_numpy_iterator().next()
predictions = model.predict_on_batch(image_batch).flatten()
# このモデルはlogits(モデルが出力した生の予測ベクトル)を返すので、シグモイド関数適用します。
predictions = tf.nn.sigmoid(predictions)
predictions = tf.where(predictions < 0.5, 0, 1)
print('Predictions:\n', predictions.numpy())
print('Labels:\n', label_batch)
plt.figure(figsize=(10, 10))
for i in range(9):
ax = plt.subplot(3, 3, i + 1)
plt.imshow(image_batch[i].astype("uint8"))
plt.title(class_names[predictions[i]])
plt.axis("off")
GDSC Osaka Univ. Edit
予測結果の確認
GDSC Osaka Univ. Edit
確認問題