Skip to content

ClasCat® AI Research

クラスキャット – 生成 AI, AI エージェント, MCP

Menu
  • ホーム
    • ClassCat® AI Research ホーム
    • クラスキャット・ホーム
  • OpenAI API
    • OpenAI Python ライブラリ 1.x : 概要
    • OpenAI ブログ
      • GPT の紹介
      • GPT ストアの紹介
      • ChatGPT Team の紹介
    • OpenAI platform 1.x
      • Get Started : イントロダクション
      • Get Started : クイックスタート (Python)
      • Get Started : クイックスタート (Node.js)
      • Get Started : モデル
      • 機能 : 埋め込み
      • 機能 : 埋め込み (ユースケース)
      • ChatGPT : アクション – イントロダクション
      • ChatGPT : アクション – Getting started
      • ChatGPT : アクション – アクション認証
    • OpenAI ヘルプ : ChatGPT
      • ChatGPTとは何ですか?
      • ChatGPT は真実を語っていますか?
      • GPT の作成
      • GPT FAQ
      • GPT vs アシスタント
      • GPT ビルダー
    • OpenAI ヘルプ : ChatGPT > メモリ
      • FAQ
    • OpenAI ヘルプ : GPT ストア
      • 貴方の GPT をフィーチャーする
    • OpenAI Python ライブラリ 0.27 : 概要
    • OpenAI platform
      • Get Started : イントロダクション
      • Get Started : クイックスタート
      • Get Started : モデル
      • ガイド : GPT モデル
      • ガイド : 画像生成 (DALL·E)
      • ガイド : GPT-3.5 Turbo 対応 微調整
      • ガイド : 微調整 1.イントロダクション
      • ガイド : 微調整 2. データセットの準備 / ケーススタディ
      • ガイド : 埋め込み
      • ガイド : 音声テキスト変換
      • ガイド : モデレーション
      • ChatGPT プラグイン : イントロダクション
    • OpenAI Cookbook
      • 概要
      • API 使用方法 : レート制限の操作
      • API 使用方法 : tiktoken でトークンを数える方法
      • GPT : ChatGPT モデルへの入力をフォーマットする方法
      • GPT : 補完をストリームする方法
      • GPT : 大規模言語モデルを扱う方法
      • 埋め込み : 埋め込みの取得
      • GPT-3 の微調整 : 分類サンプルの微調整
      • DALL-E : DALL·E で 画像を生成して編集する方法
      • DALL·E と Segment Anything で動的マスクを作成する方法
      • Whisper プロンプティング・ガイド
  • Gemini API
    • Tutorials : クイックスタート with Python (1) テキスト-to-テキスト生成
    • (2) マルチモーダル入力 / 日本語チャット
    • (3) 埋め込みの使用
    • (4) 高度なユースケース
    • クイックスタート with Node.js
    • クイックスタート with Dart or Flutter (1) 日本語動作確認
    • Gemma
      • 概要 (README)
      • Tutorials : サンプリング
      • Tutorials : KerasNLP による Getting Started
  • Keras 3
    • 新しいマルチバックエンド Keras
    • Keras 3 について
    • Getting Started : エンジニアのための Keras 入門
    • Google Colab 上のインストールと Stable Diffusion デモ
    • コンピュータビジョン – ゼロからの画像分類
    • コンピュータビジョン – 単純な MNIST convnet
    • コンピュータビジョン – EfficientNet を使用した微調整による画像分類
    • コンピュータビジョン – Vision Transformer による画像分類
    • コンピュータビジョン – 最新の MLPモデルによる画像分類
    • コンピュータビジョン – コンパクトな畳込み Transformer
    • Keras Core
      • Keras Core 0.1
        • 新しいマルチバックエンド Keras (README)
        • Keras for TensorFlow, JAX, & PyTorch
        • 開発者ガイド : Getting started with Keras Core
        • 開発者ガイド : 関数型 API
        • 開発者ガイド : シーケンシャル・モデル
        • 開発者ガイド : サブクラス化で新しい層とモデルを作成する
        • 開発者ガイド : 独自のコールバックを書く
      • Keras Core 0.1.1 & 0.1.2 : リリースノート
      • 開発者ガイド
      • Code examples
      • Keras Stable Diffusion
        • 概要
        • 基本的な使い方 (テキスト-to-画像 / 画像-to-画像変換)
        • 混合精度のパフォーマンス
        • インペインティングの簡易アプリケーション
        • (参考) KerasCV – Stable Diffusion を使用した高性能画像生成
  • TensorFlow
    • TF 2 : 初級チュートリアル
    • TF 2 : 上級チュートリアル
    • TF 2 : ガイド
    • TF 1 : チュートリアル
    • TF 1 : ガイド
  • その他
    • 🦜️🔗 LangChain ドキュメント / ユースケース
    • Stable Diffusion WebUI
      • Google Colab で Stable Diffusion WebUI 入門
      • HuggingFace モデル / VAE の導入
      • LoRA の利用
    • Diffusion Models / 拡散モデル
  • クラスキャット
    • 会社案内
    • お問合せ
    • Facebook
    • ClassCat® Blog
Menu

Keras 2 : ガイド : 転移学習と再調整

Posted on 10/29/202111/01/2021 by Sales Information

Keras 2 : ガイド : 転移学習と再調整 (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/29/2021 (keras 2.6.0)

* 本ページは、Keras の以下のドキュメントを翻訳した上で適宜、補足説明したものです:

  • Transfer learning & fine-tuning (Author: fchollet)

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

 

Keras 2 : ガイド : 転移学習と再調整

セットアップ

import numpy as np
import tensorflow as tf
from tensorflow import keras

 

イントロダクション

転移学習 は 1 つの問題上で学習された特徴を取り、そしてそれらを新しい、類似の問題上で活用することから成ります。例えば、アライグマ (= raccoon) を識別するために学習したモデルからの特徴はタヌキを識別することを意図したモデルを始動するために有用である場合があります。

転移学習はスクラッチから本格的な (= full-scale) モデルを訓練するには貴方のデータセットが少な過ぎるデータを持つようなタスクのために通常は行なわれます。

深層学習のコンテキストで転移学習の最も一般的な具現化は以下のワークフローです :

  1. 前に訓練されたモデルから層を取ります。
  2. 今後の訓練ラウンドの間にそれらが含む任意の情報を壊すことを避けるために、それらを凍結します。
  3. 凍結された層の上に幾つかの新しい、訓練可能な層を追加します。それらは古い特徴を新しいデータセット上の予測に変えるために学習します。
  4. 貴方のデータセット上で新しい層を訓練します。

最後の、オプションのステップは 再調整 で、これは上で得たモデル全体 (あるいはその一部) を解凍して、非常に低い学習率で新しいデータ上でそれを再訓練することから成ります。事前訓練された特徴を新しいデータに漸増的に適応させることによりこれは潜在的には意味のある改良を獲得できます。

最初に、Keras 訓練可能 API を詳細に調べます、これは殆どの転移学習 & 再調整ワークフローの基礎となります。

そして、ImageNet データセット上で事前訓練されたモデルを取り、そしてそれを Kaggle “猫 vs 犬” 分類データセット上で再訓練することにより典型的なワークフローを実演します。

これは Deep Learning with Python と 2016 年のブログ投稿 “building powerful image classification models using very little data” から採用されました。

 

層を凍結する : 訓練可能な属性を理解する

層 & モデルは 3 つの重み属性を持ちます :

  • weights は層の総ての重み変数のリストです。
  • trainable_weights は訓練の間に損失を最小化するために (勾配降下を通して) 更新されることを意図したそれらのリストです。
  • non_trainable_weights は訓練されることを意図していないそれらのリストです。典型的にはそれらは forward パスの間にモデルにより更新されます。

サンプル: Dense 層は 2 つの訓練可能な重み (カーネル & バイアス) を持ちます。

layer = keras.layers.Dense(3)
layer.build((None, 4))  # Create the weights

print("weights:", len(layer.weights))
print("trainable_weights:", len(layer.trainable_weights))
print("non_trainable_weights:", len(layer.non_trainable_weights))
weights: 2
trainable_weights: 2
non_trainable_weights: 0

一般に、総ての重みは訓練可能な重みです。非訓練可能な重みを持つ唯一の組込み層は BatchNormalization 層 です。訓練の間 その入力の平均と分散を追跡するために非訓練可能な重みを利用します。独自のカスタム層で非訓練可能な重みを使用する方法を学習するためには、writing new layers from scratch へのガイド を見てください。

 
サンプル: BatchNormalization 層は 2 つの訓練可能な重みと 2 つの非訓練可能な重みを持つ。

layer = keras.layers.BatchNormalization()
layer.build((None, 4))  # Create the weights

print("weights:", len(layer.weights))
print("trainable_weights:", len(layer.trainable_weights))
print("non_trainable_weights:", len(layer.non_trainable_weights))
weights: 4
trainable_weights: 2
non_trainable_weights: 2

層 & モデルはまたブーリアン属性 trainable も持ちます。その値は変更可能です。layer.trainable を False を設定すると総ての層の重みを訓練可能から非訓練可能に移します。これは層を「凍結する (= freezing)」と呼称されます : (fit() で訓練するとき、あるいは勾配更新を適用するために trainable_weights に依存する任意のカスタムループで訓練するときのいずれかの) 訓練の間に凍結された層の状態は更新されません。

 
サンプル: trainable を False に設定します

layer = keras.layers.Dense(3)
layer.build((None, 4))  # Create the weights
layer.trainable = False  # Freeze the layer

print("weights:", len(layer.weights))
print("trainable_weights:", len(layer.trainable_weights))
print("non_trainable_weights:", len(layer.non_trainable_weights))
weights: 2
trainable_weights: 0
non_trainable_weights: 2

訓練可能な重みが非訓練可能になるとき、その値は訓練の間にもはや更新されません。

# Make a model with 2 layers
layer1 = keras.layers.Dense(3, activation="relu")
layer2 = keras.layers.Dense(3, activation="sigmoid")
model = keras.Sequential([keras.Input(shape=(3,)), layer1, layer2])

# Freeze the first layer
layer1.trainable = False

# Keep a copy of the weights of layer1 for later reference
initial_layer1_weights_values = layer1.get_weights()

# Train the model
model.compile(optimizer="adam", loss="mse")
model.fit(np.random.random((2, 3)), np.random.random((2, 3)))

# Check that the weights of layer1 have not changed during training
final_layer1_weights_values = layer1.get_weights()
np.testing.assert_allclose(
    initial_layer1_weights_values[0], final_layer1_weights_values[0]
)
np.testing.assert_allclose(
    initial_layer1_weights_values[1], final_layer1_weights_values[1]
)
1/1 [==============================] - 0s 333ms/step - loss: 0.1007

layer.trainable 属性を layer.__call__() の引数 training と混同しないでください (これは層がその forward パスを推論モードか訓練モードのいずれで実行するべきかを制御します)。詳細は、Keras FAQ を見てください。

 

trainable 属性の再帰的な設定

モデルか副層 (= sublayer) を持つ任意の層上で trainable = False を設定する場合、総ての子層 (= children layers) もまた非訓練になります。

サンプル:

inner_model = keras.Sequential(
    [
        keras.Input(shape=(3,)),
        keras.layers.Dense(3, activation="relu"),
        keras.layers.Dense(3, activation="relu"),
    ]
)

model = keras.Sequential(
    [keras.Input(shape=(3,)), inner_model, keras.layers.Dense(3, activation="sigmoid"),]
)

model.trainable = False  # Freeze the outer model

assert inner_model.trainable == False  # All layers in `model` are now frozen
assert inner_model.layers[0].trainable == False  # `trainable` is propagated recursively

 

典型的な転移学習ワークフロー

これは典型的な転移学習ワークフローが Keras でどのように実装できるかに導いてくれます :

  1. 基底モデルをインスタンス化して事前訓練された重みをその中にロードします。
  2. trainable = False を設定して基底モデルの総ての層を凍結します。
  3. 基底モデルからの一つ (or 幾つか) の層の出力の上に新しいモデルを作成します。
  4. 貴方の新しいデータセット上で新しいモデルを訓練します。

代替の、より軽量なワークフローはまた次のようなものであり得ることに注意してください :

  1. 基底モデルをインスタンス化して事前訓練された重みをその中にロードします。
  2. それを通して新しいデータセットを実行してそして基底モデルからの一つ (or 幾つか) の層の出力を記録します。これは 特徴抽出 と呼ばれます。
  3. その出力を新しい、より小さなモデルのための入力データとして利用します。

2 番目のワークフローの主要な優位点は基底モデルを (訓練のエポック毎に 1 度ではなく) 貴方のデータ上 1 度実行するだけであることです。従ってそれは遥かに高速で & 安価です。

けれども、その 2 番目のワークフローに伴う問題は、それは訓練の間に貴方の新しいモデルの入力データを動的に変更することを可能にしないことです、これは例えば、データ増強を行なうときに必要です。転移学習は典型的には貴方の新しいデータセットが完全な (= full-scale) モデルをスクラッチから訓練するためには非常に少ないデータを持つときタスクのために使用され、そしてそのようなシナリオではデータ増強は非常に重要です。そのため以下では、最初のワークフローにフォーカスします。

ここに最初のワークフローが Keras でどのようなものかがあります :

最初に、事前訓練された重みで基底モデルをインスタンス化します。

base_model = keras.applications.Xception(
    weights='imagenet',  # Load weights pre-trained on ImageNet.
    input_shape=(150, 150, 3),
    include_top=False)  # Do not include the ImageNet classifier at the top.

それから、基底モデルを凍結します。

base_model.trainable = False

上に新しいモデルを作成します。

inputs = keras.Input(shape=(150, 150, 3))
# We make sure that the base_model is running in inference mode here,
# by passing `training=False`. This is important for fine-tuning, as you will
# learn in a few paragraphs.
x = base_model(inputs, training=False)
# Convert features of shape `base_model.output_shape[1:]` to vectors
x = keras.layers.GlobalAveragePooling2D()(x)
# A Dense classifier with a single unit (binary classification)
outputs = keras.layers.Dense(1)(x)
model = keras.Model(inputs, outputs)

新しいデータでモデルを訓練します。

model.compile(optimizer=keras.optimizers.Adam(),
              loss=keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=[keras.metrics.BinaryAccuracy()])
model.fit(new_dataset, epochs=20, callbacks=..., validation_data=...)

 

再調整

貴方のモデルが新しいデータ上でひとたび収束したのであれば、基底モデルの総てまたは一部を解凍してそして非常に小さい学習率でモデル全体を end-to-end に再訓練することを試すができます。

これは増加的な (= incremental) 改良を潜在的に与えられるオプションの最後のステップです。それはまた潜在的に素早い overfitting に繋がる可能性があります — それに留意してください。

凍結された層を持つモデルが収束まで訓練された後だけにこのステップを行なうことが不可欠です。もしランダムに初期化された訓練可能な層を事前訓練された特徴を保持する訓練可能な層と混在させれば、ランダムに初期化された層は訓練の間に非常に大きな勾配更新を引き起こすでしょう、これは事前訓練された特徴を破壊します。

この段階で非常に低い学習率を使用することも重要です、何故ならば典型的には非常に小さいデータセット上で、訓練の最初のラウンドにおけるよりも遥かに大規模なモデルを訓練しているからです。その結果、大きな重み更新を適用する場合非常に迅速に overffitting する危険性があります。ここでは、漸増的な方法で事前訓練された重みを再適応させることを望むだけです。

これが基底モデル全体の再調整を実装する方法です :

# Unfreeze the base model
base_model.trainable = True

# It's important to recompile your model after you make any changes
# to the `trainable` attribute of any inner layer, so that your changes
# are take into account
model.compile(optimizer=keras.optimizers.Adam(1e-5),  # Very low learning rate
              loss=keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=[keras.metrics.BinaryAccuracy()])

# Train end-to-end. Be careful to stop before you overfit!
model.fit(new_dataset, epochs=10, callbacks=..., validation_data=...)

 
compile() と trainable についての重要なノート

モデル上での compile() の呼び出しはそのモデルの動作を「凍結する」ことを意図しています。これはモデルがコンパイルされた時の訓練可能な属性値は再度 compile が呼び出されるまでそのモデルのライフタイムを通して保存されるべきであることを含蓄します。こうして、任意の訓練可能な値を変更する場合、貴方の変更が考慮されるためにモデル上で compile() を再度呼び出すことを確実にしてください。

 
BatchNormalization 層についての重要なノート

多くの画像モデルは BatchNormalization 層を含みます。その層は考えうる総てにおいて特別なケースです。ここに留意すべき幾つかのことがあります。

  • BatchNormalization は訓練の間に更新されるべき 2 つの非訓練可能な重みを含みます。これらは入力の平均と分散を追跡する変数です。
  • bn_layer.trainable = False を設定するとき、BatchNormalization 層は推論モードで実行され、そしてその平均 & 分散統計値を更新しません。これは一般には他の層には当てはまりません、というのは 重みの訓練可能性 & 推論/訓練モードは 2 つの直交する概念だからです。しかし 2 つは BatchNormalization 層の場合には結び付けられます。
  • 再調整を行なうために BatchNormalization 層を含むモデルを解凍するとき、基底モデルを呼び出すとき training=False を渡して BatchNormalization 層を推論モードに保持するべきです。そうでないと非訓練可能な重みに適用される更新がモデルが学習したものを突然に破壊します。

このガイドの最後の end-to-end サンプルでこのパターンを実際に見ます。

 

カスタム訓練ループを使用する転移学習 & 再調整

fit() の代わりに、独自の低位訓練ループを使用している場合、ワークフローは本質的には同じままです。勾配更新を適用するときリスト model.trainable_weights を考慮することだけに注意すべきです :

# Create base model
base_model = keras.applications.Xception(
    weights='imagenet',
    input_shape=(150, 150, 3),
    include_top=False)
# Freeze base model
base_model.trainable = False

# Create new model on top.
inputs = keras.Input(shape=(150, 150, 3))
x = base_model(inputs, training=False)
x = keras.layers.GlobalAveragePooling2D()(x)
outputs = keras.layers.Dense(1)(x)
model = keras.Model(inputs, outputs)

loss_fn = keras.losses.BinaryCrossentropy(from_logits=True)
optimizer = keras.optimizers.Adam()

# Iterate over the batches of a dataset.
for inputs, targets in new_dataset:
    # Open a GradientTape.
    with tf.GradientTape() as tape:
        # Forward pass.
        predictions = model(inputs)
        # Compute the loss value for this batch.
        loss_value = loss_fn(targets, predictions)

    # Get gradients of loss wrt the *trainable* weights.
    gradients = tape.gradient(loss_value, model.trainable_weights)
    # Update the weights of the model.
    optimizer.apply_gradients(zip(gradients, model.trainable_weights))

Likewise for fine-tuning.

 

end-to-end サンプル: 猫 vs. 犬データセット上で画像分類モデルを再調整する

これらのコンセプトを固めるために、具体的な end-to-end 転移学習 & 再調整サンプルを通り抜けましょう。ImageNet 上で事前訓練された、Xception モデルをロードし、そしてそれを Kaggle “猫 vs. 犬” 分類データセット上で使用します。

 

データを得る

最初に、TFDS を使用して猫 vs. 犬データセットを取得しましょう。独自のデータセットを持つ場合、クラス専用フォルダーにファイルされたディスク上の画像のセットから同様のラベル付けられたデータセット・オブジェクトを生成するために貴方は多分ユティリティ tf.keras.preprocessing.image_dataset_from_directory を使用することを望むでしょう。

転移学習は非常に小さいデータセットで作業するとき最も有用です。データセットを小さく保持するために、訓練のために元の訓練データ (25,000 画像) の 40%、検証のために 10%、そしてテストのために 10% を利用します。

import tensorflow_datasets as tfds

tfds.disable_progress_bar()

train_ds, validation_ds, test_ds = tfds.load(
    "cats_vs_dogs",
    # Reserve 10% for validation and 10% for test
    split=["train[:40%]", "train[40%:50%]", "train[50%:60%]"],
    as_supervised=True,  # Include labels
)

print("Number of training samples: %d" % tf.data.experimental.cardinality(train_ds))
print(
    "Number of validation samples: %d" % tf.data.experimental.cardinality(validation_ds)
)
print("Number of test samples: %d" % tf.data.experimental.cardinality(test_ds))
Number of training samples: 9305
Number of validation samples: 2326
Number of test samples: 2326

これらは訓練データセットの最初の 9 画像です — ご覧のように、それらは総て異なるサイズです。

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 10))
for i, (image, label) in enumerate(train_ds.take(9)):
    ax = plt.subplot(3, 3, i + 1)
    plt.imshow(image)
    plt.title(int(label))
    plt.axis("off")

ラベル 1 が「犬」でラベル 0 が「猫」であることも見れます。

 

データを標準化する

raw 画像は様々なサイズを持ちます。加えて、各ピクセルは 0 と 255 の間の 3 つの整数値 (RGB レベル値) から成ります。これはニューラルネットワークに供給するために上手く適合しません。私達は 2 つのことを行なう必要があります :

  • 固定画像サイズに標準化する。150×150 を選択します。
  • ピクセル値を -1 と 1 の間に正規化する。モデル自身の一部として Normalization 層を使用してこれを行ないます。

一般に、既に前処理されたデータを取るモデルに対して、入力として raw データを取るモデルを開発することは良い実践です。その理由は、モデルが前処理されたデータを想定する場合、他で (web ブラウザ、モバイル app で) それを使用するためにモデルをエクスポートするたびに、正確に同じ前処理パイプラインを再実装する必要があるためです。それは非常に素早く非常に技巧的になります。そのためモデルに達する前に最小限の量の前処理を行なうべきです。

ここでは、データパイプラインで画像リサイズを行ない (何故ならば深層ニューラルネットワークはデータの連続的なバッチを処理するだけだからです)、そしてモデルの一部として入力値スケーリングを行ないます、それを作成するときに。

画像を 150×150 にリサイズしましょう :

size = (150, 150)

train_ds = train_ds.map(lambda x, y: (tf.image.resize(x, size), y))
validation_ds = validation_ds.map(lambda x, y: (tf.image.resize(x, size), y))
test_ds = test_ds.map(lambda x, y: (tf.image.resize(x, size), y))

更に、データをバッチ化してローディング・スピードを最適化するためにキャッシングと先取り (= prefetching) を利用しましょう。

batch_size = 32

train_ds = train_ds.cache().batch(batch_size).prefetch(buffer_size=10)
validation_ds = validation_ds.cache().batch(batch_size).prefetch(buffer_size=10)
test_ds = test_ds.cache().batch(batch_size).prefetch(buffer_size=10)

 

ランダムデータ増強を使用する

大規模な画像データセットを持たないとき、ランダムな水平反転や小さなランダム回転のような、ランダムでありながら現実的な変換を適用することでサンプルの多様性を人工的に導入することは良い実践です。これは overfitting をスローダウンさせる一方で訓練データの様々な様相にモデルを晒す役に立ちます。

from tensorflow import keras
from tensorflow.keras import layers

data_augmentation = keras.Sequential(
    [layers.RandomFlip("horizontal"), layers.RandomRotation(0.1),]
)

様々なランダム変換の後に最初のバッチの最初の画像がどのように見えるか可視化しましょう :

import numpy as np

for images, labels in train_ds.take(1):
    plt.figure(figsize=(10, 10))
    first_image = images[0]
    for i in range(9):
        ax = plt.subplot(3, 3, i + 1)
        augmented_image = data_augmentation(
            tf.expand_dims(first_image, 0), training=True
        )
        plt.imshow(augmented_image[0].numpy().astype("int32"))
        plt.title(int(labels[0]))
        plt.axis("off")

 

モデルを構築する

さて、先に説明したブループリントに従ってモデルを構築しましょう。

以下に注意してください :

  • (初期化時に [0, 255] 範囲内の) 入力値を [-1, 1] 範囲にスケールするために Rescaling 層を追加します。
  • 正則化のために、分類層の前に Dropout 層を追加します。
  • 基底モデルを呼び出すときに、それが推論モードで動作するように training=False を渡すことを確実にします、その結果 batchnorm 統計値は再調整のために基底モデルを解凍した後でさえ更新されません。
base_model = keras.applications.Xception(
    weights="imagenet",  # Load weights pre-trained on ImageNet.
    input_shape=(150, 150, 3),
    include_top=False,
)  # Do not include the ImageNet classifier at the top.

# Freeze the base_model
base_model.trainable = False

# Create new model on top
inputs = keras.Input(shape=(150, 150, 3))
x = data_augmentation(inputs)  # Apply random data augmentation

# Pre-trained Xception weights requires that input be scaled
# from (0, 255) to a range of (-1., +1.), the rescaling layer
# outputs: `(inputs * scale) + offset`
scale_layer = keras.layers.Rescaling(scale=1 / 127.5, offset=-1)
x = scale_layer(x)

# The base model contains batchnorm layers. We want to keep them in inference mode
# when we unfreeze the base model for fine-tuning, so we make sure that the
# base_model is running in inference mode here.
x = base_model(x, training=False)
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dropout(0.2)(x)  # Regularize with dropout
outputs = keras.layers.Dense(1)(x)
model = keras.Model(inputs, outputs)

model.summary()
Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_5 (InputLayer)         [(None, 150, 150, 3)]     0         
_________________________________________________________________
sequential_3 (Sequential)    (None, 150, 150, 3)       0         
_________________________________________________________________
rescaling (Rescaling)        (None, 150, 150, 3)       0         
_________________________________________________________________
xception (Functional)        (None, 5, 5, 2048)        20861480  
_________________________________________________________________
global_average_pooling2d (Gl (None, 2048)              0         
_________________________________________________________________
dropout (Dropout)            (None, 2048)              0         
_________________________________________________________________
dense_7 (Dense)              (None, 1)                 2049      
=================================================================
Total params: 20,863,529
Trainable params: 2,049
Non-trainable params: 20,861,480
_________________________________________________________________

 

トップ層を訓練する

model.compile(
    optimizer=keras.optimizers.Adam(),
    loss=keras.losses.BinaryCrossentropy(from_logits=True),
    metrics=[keras.metrics.BinaryAccuracy()],
)

epochs = 20
model.fit(train_ds, epochs=epochs, validation_data=validation_ds)
Epoch 1/20
291/291 [==============================] - 133s 451ms/step - loss: 0.1670 - binary_accuracy: 0.9267 - val_loss: 0.0830 - val_binary_accuracy: 0.9716
Epoch 2/20
291/291 [==============================] - 135s 465ms/step - loss: 0.1208 - binary_accuracy: 0.9502 - val_loss: 0.0768 - val_binary_accuracy: 0.9716
Epoch 3/20
291/291 [==============================] - 135s 463ms/step - loss: 0.1062 - binary_accuracy: 0.9572 - val_loss: 0.0757 - val_binary_accuracy: 0.9716
Epoch 4/20
291/291 [==============================] - 137s 469ms/step - loss: 0.1024 - binary_accuracy: 0.9554 - val_loss: 0.0733 - val_binary_accuracy: 0.9725
Epoch 5/20
291/291 [==============================] - 137s 470ms/step - loss: 0.1004 - binary_accuracy: 0.9587 - val_loss: 0.0735 - val_binary_accuracy: 0.9729
Epoch 6/20
291/291 [==============================] - 136s 467ms/step - loss: 0.0979 - binary_accuracy: 0.9577 - val_loss: 0.0747 - val_binary_accuracy: 0.9708
Epoch 7/20
291/291 [==============================] - 134s 462ms/step - loss: 0.0998 - binary_accuracy: 0.9596 - val_loss: 0.0706 - val_binary_accuracy: 0.9725
Epoch 8/20
291/291 [==============================] - 133s 457ms/step - loss: 0.1029 - binary_accuracy: 0.9592 - val_loss: 0.0720 - val_binary_accuracy: 0.9733
Epoch 9/20
291/291 [==============================] - 135s 466ms/step - loss: 0.0937 - binary_accuracy: 0.9625 - val_loss: 0.0707 - val_binary_accuracy: 0.9721
Epoch 10/20
291/291 [==============================] - 137s 472ms/step - loss: 0.0967 - binary_accuracy: 0.9580 - val_loss: 0.0720 - val_binary_accuracy: 0.9712
Epoch 11/20
291/291 [==============================] - 135s 463ms/step - loss: 0.0961 - binary_accuracy: 0.9612 - val_loss: 0.0802 - val_binary_accuracy: 0.9699
Epoch 12/20
291/291 [==============================] - 134s 460ms/step - loss: 0.0963 - binary_accuracy: 0.9638 - val_loss: 0.0721 - val_binary_accuracy: 0.9716
Epoch 13/20
291/291 [==============================] - 136s 468ms/step - loss: 0.0925 - binary_accuracy: 0.9635 - val_loss: 0.0736 - val_binary_accuracy: 0.9686
Epoch 14/20
291/291 [==============================] - 138s 476ms/step - loss: 0.0909 - binary_accuracy: 0.9624 - val_loss: 0.0766 - val_binary_accuracy: 0.9703
Epoch 15/20
291/291 [==============================] - 136s 467ms/step - loss: 0.0949 - binary_accuracy: 0.9598 - val_loss: 0.0704 - val_binary_accuracy: 0.9725
Epoch 16/20
291/291 [==============================] - 133s 456ms/step - loss: 0.0969 - binary_accuracy: 0.9586 - val_loss: 0.0722 - val_binary_accuracy: 0.9708
Epoch 17/20
291/291 [==============================] - 135s 464ms/step - loss: 0.0913 - binary_accuracy: 0.9635 - val_loss: 0.0718 - val_binary_accuracy: 0.9716
Epoch 18/20
291/291 [==============================] - 137s 472ms/step - loss: 0.0915 - binary_accuracy: 0.9639 - val_loss: 0.0727 - val_binary_accuracy: 0.9725
Epoch 19/20
291/291 [==============================] - 134s 460ms/step - loss: 0.0938 - binary_accuracy: 0.9631 - val_loss: 0.0707 - val_binary_accuracy: 0.9733
Epoch 20/20
291/291 [==============================] - 134s 460ms/step - loss: 0.0971 - binary_accuracy: 0.9609 - val_loss: 0.0714 - val_binary_accuracy: 0.9716

<keras.callbacks.History at 0x7f4494e38f70>

(訳注 : Tesla P100 実験結果)

Epoch 1/20
291/291 [==============================] - 35s 61ms/step - loss: 0.1682 - binary_accuracy: 0.9286 - val_loss: 0.0827 - val_binary_accuracy: 0.9699
Epoch 2/20
291/291 [==============================] - 15s 51ms/step - loss: 0.1130 - binary_accuracy: 0.9517 - val_loss: 0.0758 - val_binary_accuracy: 0.9729
Epoch 3/20
291/291 [==============================] - 15s 51ms/step - loss: 0.1108 - binary_accuracy: 0.9542 - val_loss: 0.0749 - val_binary_accuracy: 0.9712
Epoch 4/20
291/291 [==============================] - 15s 51ms/step - loss: 0.1073 - binary_accuracy: 0.9563 - val_loss: 0.0733 - val_binary_accuracy: 0.9708
Epoch 5/20
291/291 [==============================] - 15s 51ms/step - loss: 0.1023 - binary_accuracy: 0.9584 - val_loss: 0.0704 - val_binary_accuracy: 0.9738
Epoch 6/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0974 - binary_accuracy: 0.9563 - val_loss: 0.0702 - val_binary_accuracy: 0.9738
Epoch 7/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0961 - binary_accuracy: 0.9612 - val_loss: 0.0772 - val_binary_accuracy: 0.9721
Epoch 8/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0992 - binary_accuracy: 0.9579 - val_loss: 0.0725 - val_binary_accuracy: 0.9708
Epoch 9/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0994 - binary_accuracy: 0.9606 - val_loss: 0.0706 - val_binary_accuracy: 0.9733
Epoch 10/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0908 - binary_accuracy: 0.9610 - val_loss: 0.0766 - val_binary_accuracy: 0.9708
Epoch 11/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0942 - binary_accuracy: 0.9625 - val_loss: 0.0746 - val_binary_accuracy: 0.9695
Epoch 12/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0949 - binary_accuracy: 0.9601 - val_loss: 0.0704 - val_binary_accuracy: 0.9721
Epoch 13/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0970 - binary_accuracy: 0.9612 - val_loss: 0.0712 - val_binary_accuracy: 0.9716
Epoch 14/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0955 - binary_accuracy: 0.9629 - val_loss: 0.0701 - val_binary_accuracy: 0.9729
Epoch 15/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0966 - binary_accuracy: 0.9600 - val_loss: 0.0702 - val_binary_accuracy: 0.9725
Epoch 16/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0916 - binary_accuracy: 0.9613 - val_loss: 0.0776 - val_binary_accuracy: 0.9682
Epoch 17/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0909 - binary_accuracy: 0.9607 - val_loss: 0.0754 - val_binary_accuracy: 0.9708
Epoch 18/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0955 - binary_accuracy: 0.9620 - val_loss: 0.0709 - val_binary_accuracy: 0.9725
Epoch 19/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0904 - binary_accuracy: 0.9631 - val_loss: 0.0722 - val_binary_accuracy: 0.9712
Epoch 20/20
291/291 [==============================] - 15s 51ms/step - loss: 0.0969 - binary_accuracy: 0.9592 - val_loss: 0.0701 - val_binary_accuracy: 0.9716
CPU times: user 2min 47s, sys: 12 s, total: 2min 59s
Wall time: 6min 18s

 

モデル全体の再調整のラウンドを行なう

最後に、基底モデルを解凍してそしてモデル全体を低い学習率で end-to-end に訓練しましょう。

重要なことは、基底モデルは訓練可能になりますが、それは依然として推論モードで動作していることです、何故ならばモデルを構築するときにそれを呼び出すとき training=False を渡したからです。これは、バッチ正規化層内部ではバッチ統計値を更新しないことを意味しています。それらが行なうのであれば、それらはそこまでにモデルにより学習された表現に大きな打撃を与えてしまいます (= wreck havoc)。

# Unfreeze the base_model. Note that it keeps running in inference mode
# since we passed `training=False` when calling it. This means that
# the batchnorm layers will not update their batch statistics.
# This prevents the batchnorm layers from undoing all the training
# we've done so far.
base_model.trainable = True
model.summary()

model.compile(
    optimizer=keras.optimizers.Adam(1e-5),  # Low learning rate
    loss=keras.losses.BinaryCrossentropy(from_logits=True),
    metrics=[keras.metrics.BinaryAccuracy()],
)

epochs = 10
model.fit(train_ds, epochs=epochs, validation_data=validation_ds)
Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_5 (InputLayer)         [(None, 150, 150, 3)]     0         
_________________________________________________________________
sequential_3 (Sequential)    (None, 150, 150, 3)       0         
_________________________________________________________________
rescaling (Rescaling)        (None, 150, 150, 3)       0         
_________________________________________________________________
xception (Functional)        (None, 5, 5, 2048)        20861480  
_________________________________________________________________
global_average_pooling2d (Gl (None, 2048)              0         
_________________________________________________________________
dropout (Dropout)            (None, 2048)              0         
_________________________________________________________________
dense_7 (Dense)              (None, 1)                 2049      
=================================================================
Total params: 20,863,529
Trainable params: 20,809,001
Non-trainable params: 54,528
_________________________________________________________________
Epoch 1/10
291/291 [==============================] - 567s 2s/step - loss: 0.0749 - binary_accuracy: 0.9689 - val_loss: 0.0605 - val_binary_accuracy: 0.9776
Epoch 2/10
291/291 [==============================] - 551s 2s/step - loss: 0.0559 - binary_accuracy: 0.9770 - val_loss: 0.0507 - val_binary_accuracy: 0.9798
Epoch 3/10
291/291 [==============================] - 545s 2s/step - loss: 0.0444 - binary_accuracy: 0.9832 - val_loss: 0.0502 - val_binary_accuracy: 0.9807
Epoch 4/10
291/291 [==============================] - 558s 2s/step - loss: 0.0365 - binary_accuracy: 0.9874 - val_loss: 0.0506 - val_binary_accuracy: 0.9807
Epoch 5/10
291/291 [==============================] - 550s 2s/step - loss: 0.0276 - binary_accuracy: 0.9890 - val_loss: 0.0477 - val_binary_accuracy: 0.9802
Epoch 6/10
291/291 [==============================] - 588s 2s/step - loss: 0.0206 - binary_accuracy: 0.9916 - val_loss: 0.0444 - val_binary_accuracy: 0.9832
Epoch 7/10
291/291 [==============================] - 542s 2s/step - loss: 0.0206 - binary_accuracy: 0.9923 - val_loss: 0.0502 - val_binary_accuracy: 0.9828
Epoch 8/10
291/291 [==============================] - 544s 2s/step - loss: 0.0153 - binary_accuracy: 0.9939 - val_loss: 0.0509 - val_binary_accuracy: 0.9819
Epoch 9/10
291/291 [==============================] - 548s 2s/step - loss: 0.0156 - binary_accuracy: 0.9934 - val_loss: 0.0610 - val_binary_accuracy: 0.9807
Epoch 10/10
291/291 [==============================] - 546s 2s/step - loss: 0.0176 - binary_accuracy: 0.9936 - val_loss: 0.0561 - val_binary_accuracy: 0.9789

<keras.callbacks.History at 0x7f4495056040>

(訳注 : Tesla P100 実験結果)

Epoch 1/10
291/291 [==============================] - 71s 228ms/step - loss: 0.0807 - binary_accuracy: 0.9655 - val_loss: 0.0529 - val_binary_accuracy: 0.9785
Epoch 2/10
291/291 [==============================] - 65s 222ms/step - loss: 0.0529 - binary_accuracy: 0.9784 - val_loss: 0.0525 - val_binary_accuracy: 0.9807
Epoch 3/10
291/291 [==============================] - 65s 223ms/step - loss: 0.0455 - binary_accuracy: 0.9830 - val_loss: 0.0542 - val_binary_accuracy: 0.9794
Epoch 4/10
291/291 [==============================] - 65s 223ms/step - loss: 0.0344 - binary_accuracy: 0.9868 - val_loss: 0.0490 - val_binary_accuracy: 0.9807
Epoch 5/10
291/291 [==============================] - 65s 224ms/step - loss: 0.0251 - binary_accuracy: 0.9910 - val_loss: 0.0441 - val_binary_accuracy: 0.9824
Epoch 6/10
291/291 [==============================] - 65s 223ms/step - loss: 0.0219 - binary_accuracy: 0.9922 - val_loss: 0.0459 - val_binary_accuracy: 0.9819
Epoch 7/10
291/291 [==============================] - 65s 223ms/step - loss: 0.0226 - binary_accuracy: 0.9909 - val_loss: 0.0544 - val_binary_accuracy: 0.9824
Epoch 8/10
291/291 [==============================] - 65s 222ms/step - loss: 0.0202 - binary_accuracy: 0.9929 - val_loss: 0.0443 - val_binary_accuracy: 0.9828
Epoch 9/10
291/291 [==============================] - 65s 223ms/step - loss: 0.0149 - binary_accuracy: 0.9943 - val_loss: 0.0516 - val_binary_accuracy: 0.9811
Epoch 10/10
291/291 [==============================] - 65s 222ms/step - loss: 0.0121 - binary_accuracy: 0.9962 - val_loss: 0.0436 - val_binary_accuracy: 0.9819

After 10 epochs, fine-tuning gains us a nice improvement here.

 

以上



クラスキャット

最近の投稿

  • LangGraph 0.5 : エージェント開発 : ワークフローとエージェント
  • LangGraph 0.5 : エージェント開発 : エージェントの実行
  • LangGraph 0.5 : エージェント開発 : prebuilt コンポーネントを使用したエージェント開発
  • LangGraph 0.5 : Get started : ローカルサーバの実行
  • LangGraph 0.5 on Colab : Get started : human-in-the-loop 制御の追加

タグ

AutoGen (13) ClassCat Press Release (20) ClassCat TF/ONNX Hub (11) DGL 0.5 (14) Eager Execution (7) Edward (17) FLUX.1 (16) Gemini (20) HuggingFace Transformers 4.5 (10) HuggingFace Transformers 4.6 (7) HuggingFace Transformers 4.29 (9) Keras 2 Examples (98) Keras 2 Guide (16) Keras 3 (10) Keras Release Note (17) Kubeflow 1.0 (10) LangChain (45) LangGraph (24) LangGraph 0.5 (8) MediaPipe 0.8 (11) Model Context Protocol (16) NNI 1.5 (16) OpenAI Agents SDK (8) OpenAI Cookbook (13) OpenAI platform (10) OpenAI platform 1.x (10) OpenAI ヘルプ (8) TensorFlow 2.0 Advanced Tutorials (33) TensorFlow 2.0 Advanced Tutorials (Alpha) (15) TensorFlow 2.0 Advanced Tutorials (Beta) (16) TensorFlow 2.0 Guide (10) TensorFlow 2.0 Guide (Alpha) (16) TensorFlow 2.0 Guide (Beta) (9) TensorFlow 2.0 Release Note (12) TensorFlow 2.0 Tutorials (20) TensorFlow 2.0 Tutorials (Alpha) (14) TensorFlow 2.0 Tutorials (Beta) (12) TensorFlow 2.4 Guide (24) TensorFlow Deploy (8) TensorFlow Get Started (7) TensorFlow Probability (9) TensorFlow Programmer's Guide (22) TensorFlow Release Note (18) TensorFlow Tutorials (33) TF-Agents 0.4 (11)
2021年10月
月 火 水 木 金 土 日
 123
45678910
11121314151617
18192021222324
25262728293031
« 8月   11月 »
© 2025 ClasCat® AI Research | Powered by Minimalist Blog WordPress Theme