1 of 51

転移学習を用いた

画像分類

Explore ML

2 of 51

復習: TensorFlowについて説明し合いましょう。

3 of 51

TensorFlowはデータフローと微分可能�プログラミングを提供する�無償のOSSライブラリです。

記号演算ライブラリであり、ニューラルネットワークなどの機械学習�アプリケーションに利用できます。

OSS = Open Source Software �(利用者の目的を問わずソースコードを使用、調査、再利用、�修正、拡張、再配布が可能なソフトウェアの総称である from Wiki)

GDSC Osaka Univ. Edit

4 of 51

本日使用するデータセット

GDSC Osaka Univ. Edit

5 of 51

一般的な機械学習のワークフロー

データ収集

モデルの

訓練と検証

問題定義

予測と評価

ユーザ

6 of 51

転移学習のワークフロー

データ

分析

分類レイヤー

の再学習

予測と評価

事前学習済み

モデルの再利用

7 of 51

事前学習済みモデルとは何でしょうか?

8 of 51

事前学習済みモデルとは、

大規模データセットを用いて,事前に学習したモデルです。 

転移学習により、任意のタスクに転用することができます。

Tips:大規模な画像分類タスクを学習したモデルを利用することが多い.

GDSC Osaka Univ. Edit

9 of 51

転移学習の概略図

ソースモデル

大量のデータ

(ソースドメイン)

出力

ラベル

ソースモデル

出力

ラベル

対象データ

(対象のドメイン)

GDSC Osaka Univ. Edit

10 of 51

画像分類プログラムの作成

  1. https://www.tensorflow.org/beta/tutorials/images/transfer_learning

  • Google Colaboratory でファイルを開く

  • Googleアカウントでサインイン

  • ランタイムに接続

  • プログラムを実行

11 of 51

以後はチュートリアルの補助スライド

(講義では使用しない)

STOP

12 of 51

ライブラリの準備

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

13 of 51

データのダウンロード

_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

14 of 51

フォルダの構成

GDSC Osaka Univ. Original

cats_and_dogs_filtered

train

validation

cats

dogs

PATH

train_dir

cats0.jpg

cats1.jpg

validation_dir

15 of 51

データセットクラスの作成

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

16 of 51

学習データの表示

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

17 of 51

[補足] tf.dataモジュール (1/2)

モデルの学習を行う際、データに対して以下の処理が必要となる。

  ・データシャッフル

  ・バッチ化

  ・データの繰り返し抽出

  ・高速なバッチ抽出

➡ このような複雑な処理は、tf.data APIを使えば容易に実装できる。

GDSC Osaka Univ. Original

18 of 51

[補足] 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

19 of 51

テストセットの作成

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

20 of 51

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

21 of 51

Data Augmentation (データのかさ増し)

 過学習を避け、汎化性能を高めるために、現実的にありうる範囲で� サンプルに変形を加えます。(反転、回転、拡大など)

水平反転

回転

GDSC Osaka Univ. Original

22 of 51

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

23 of 51

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

24 of 51

ピクセル値の正規化

preprocess_input =

tf.keras.applications.mobilenet_v2.preprocess_input

モデルに含まれる前処理のメソッドを使用して、ピクセル値を[0, 255]から[-1, 1]に正規化

GDSC Osaka Univ. Edit

25 of 51

事前学習済みモデルの読み込み

# 学習済みMobileNet V2をベースモデルに使用

IMG_SHAPE = IMG_SIZE + (3,)

base_model =

tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,

                   include_top=False,

  weights='imagenet')

26 of 51

MobileNet V2

27 of 51

MobileNet V2の詳細

1×1畳み込み層

ReLU層

1×1畳み込み層

恒等関数層

3×3Dwise層

ReLU層

線形

ボトルネック

線形

ボトルネック

MobileNet V2のモジュール

  • Residual Connection(残差接続)

  • 線形ボトルネック

  • Depthwise Separatable Convolution(深さ方向分離可能畳み込み)

Residual Connection

GDSC Osaka Univ. Original

28 of 51

Residual Connection (残差接続)

GDSC Osaka Univ. Original

x : 入力, H(x) : 出力

F(x) = H(x) - x

F(x) : 出力から入力を引いた「残差」

残差を学習することで、そのブロックは、

非常に小さな変換」だけを担当できる。

  層をより深くすることが可能

29 of 51

ベースモデルの出力を確認

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

30 of 51

base_model.trainable = False

# ベースモデルの構造を確認

base_model.summary()

ベースモデルの重みを固定

31 of 51

出力層の追加

プーリング層

全結合層

MobileNet V2の出力

最終出力

(Dog or Cat)

GDSC Osaka Univ. Original

32 of 51

出力層の設定 (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個の特徴を平均化し、

チャネルごとに単一の値に変換

33 of 51

出力層の設定 (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

34 of 51

モデルの構築

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

35 of 51

モデルのコンパイル

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

36 of 51

モデルの確認

model.summary()

len(model.trainable_variables)

GDSC Osaka Univ. Edit

37 of 51

実行結果

38 of 51

モデルの学習

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

39 of 51

モデルの学習

history = model.fit(train_dataset,

epochs=initial_epochs,

validation_data=validation_dataset)

GDSC Osaka Univ. Edit

40 of 51

学習曲線の表示

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

41 of 51

学習曲線の表示

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

42 of 51

Fine Tuning

43 of 51

モデルの学習

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

44 of 51

モデルのコンパイル

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

45 of 51

モデルの学習

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

46 of 51

学習曲線の表示 (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

47 of 51

学習曲線の表示 (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

48 of 51

データの評価と予測

loss, accuracy = model.evaluate(test_dataset)

print('Test accuracy :', accuracy)

49 of 51

データの評価と予測

# テストセットからバッチを取得します。

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

50 of 51

予測結果の確認

GDSC Osaka Univ. Edit

51 of 51

確認問題

  • 特徴抽出に事前学習済みモデルを使用する利点は何でしたか?

  • 事前学習済みモデルをfine-tuningする為に何を行いましたか