Path: blob/master/site/ja/tutorials/images/transfer_learning.ipynb
25118 views
Copyright 2019 The TensorFlow Authors.
転移学習とファインチューニング
このチュートリアルでは、転移学習を使用して、事前トレーニング済みネットワークから猫や犬の画像を分類する方法を紹介します。
事前トレーニング済みモデルは、通常は大規模な画像分類タスクなどの大規模なデータセットで事前トレーニング済みの保存されたネットワークです。事前トレーニング済みモデルをそのまま使用したり、転移学習を使用してこのモデルを任意のタスクにカスタマイズしたりすることができます。
画像分類のための転移学習の背後にある考え方は、モデルが大規模かつ十分に一般的なデータセットでトレーニングされていれば、そのモデルは視覚世界の一般的なモデルとして効果的に機能するというものです。それにより、最初から大規模なデータセット上で大規模なモデルをトレーニングを行わずに、これらの学習した特徴マップを活用することができます。
このノートブックでは、トレーニング済みモデルをカスタマイズする 2 つの方法を試します。
特徴抽出:前のネットワークで学習した表現を使用して、新しいサンプルから意味のある特徴を抽出します。事前トレーニング済みモデルの上に新規にトレーニングされる新しい分類器を追加するだけで、データセットで前に学習した特徴マップを再利用できるようになります。
モデル全体を(再)トレーニングする必要はありません。ベースとなる畳み込みネットワークには、画像分類に一般的に有用な特徴がすでに含まれています。ただし、事前トレーニング済みモデルの最後の分類部分は元の分類タスクに固有で、その後はモデルがトレーニングされたクラスのセットに固有です。
ファインチューニング:凍結された基本モデルの最上位レイヤーのいくつかを解凍し、新たに追加された分類器レイヤーと解凍した基本モデルの最後のレイヤーの両方を合わせてトレーニングします。これにより、基本モデルの高次の特徴表現を「ファインチューニング」して、特定のタスクにより関連性を持たせることができます。
一般的な機械学習のワークフローに従います。
データを調べ、理解する
入力パイプラインを構築し、この場合は Keras ImageDataGenerator を使用する
モデルを作成する
事前トレーニング済みの基本モデル(および事前トレーニング済みの重み)を読み込む
分類レイヤーを上に重ねる
モデルをトレーニングする
モデルを評価する
データの前処理をする
データをダウンロードする
このチュートリアルでは、数千枚の犬猫の画像を含むデータセットを使用します。画像を含む zip ファイルをダウンロードして解凍した後、tf.keras.utils.image_dataset_from_directory
ユーティリティを使用して tf.data.Dataset
を作成し、トレーニングと検証を行います。画像の読み込みに関する詳細は、このチュートリアルをご覧ください。
トレーニングセットの最初の 9 枚の画像とラベルを表示します。
元のデータセットにはテストセットが含まれていないので、テストセットを作成します。作成には、tf.data.experimental.cardinality
を使用して検証セットで利用可能なデータのバッチ数を調べ、そのうちの 20% をテストセットに移動します。
パフォーマンスのためにデータセットを構成する
バッファ付きプリフェッチを使用して、I/O のブロッキングなしでディスクから画像を読み込みます。この手法の詳細についてはデータパフォーマンスガイドをご覧ください。
データ増強を使用する
注意: これらのレイヤーは、トレーニング中に Model.fit
を呼び出した場合にのみアクティブです。モデルが Model.evaluate
、Model.predict
、または Model.call
の推論モードで使用されている場合には非アクティブです。
これらのレイヤーを同じ画像に繰り返して適用し、結果を見てみましょう。
ピクセル値をリスケールする
すぐに tf.keras.applications.MobileNetV2
をダウンロードして、基本モデルとして使用します。このモデルはピクセル値 [-1,1]
を想定していますが、この時点での画像のピクセル値は [0, 255]
です。ピクセル値のリスケールには、モデルに含まれる前処理のメソッドを使用します。
注意: 別の方法として、tf.keras.layers.Rescaling
を使用して、ピクセル値を [0, 255]
から [-1, 1]
にリスケールすることも可能です。
注意: 他の tf.keras.applications
を使用する場合は、API ドキュメントを確認してピクセル値が [-1,1]
または [0,1]
を要求しているか確かめるか、あるいは含まれている関数 preprocess_input
を使用します。
事前トレーニング済み畳み込みニューラルネットワークから基本モデルを作成する
Google が開発した MobileNet V2 モデルから基本モデルを作成します。これは、140 万枚の画像と 1000 クラスで構成された大規模データセットである ImageNet データセットによる事前トレーニング済みのモデルです。ImageNet は、jackfruit
や syringe
のような多彩なカテゴリを持つ研究用トレーニングデータセットです。この知識の基盤が、特定のデータセットから猫と犬を分類するのに有用になります。
まず、特徴抽出に使用する MobileNet V2 のレイヤーを選択する必要があります。最後の分類レイヤー(ほとんどの機械学習モデルの図では、下から上に向かうため、「上」にあります)はあまり役には立ちません。 その代わりに、平坦化演算の前の最後のレイヤーに依存するのが一般的です。このレイヤーは「ボトルネックレイヤー」と呼ばれます。ボトルネックレイヤーの特徴には、最終/最上位レイヤーよりも一般性が保持されています。
はじめに、ImageNet でトレーニングした重みで事前に読み込んだ MobileNet V2 モデルをインスタンス化します。引数 include_top=False を指定して、上位の分類レイヤーを含まない、特徴抽出に理想的なネットワークを読み込みます。
この特徴抽出器は、各 160x160x3
の画像を 5x5x1280
の特徴ブロックに変換します。 これで画像のバッチ例がどうなるかを見てみましょう。
特徴を抽出する
このステップでは、前のステップで作成した畳み込みベースを凍結させ、特徴抽出器として使用します。さらに、その上に分類器を追加して、最上位の分類器のトレーニングを行います。
畳み込みベースを凍結させる
モデルをコンパイルしてトレーニングする前に、畳み込みベースを凍結させることは重要です。(layer.trainable = False と設定して) 凍結させると、トレーニング中に特定のレイヤーの重みは更新されなくなります。MobileNet V2 には多くのレイヤーがありますが、モデル全体の trainable
フラグを False に設定すれば、すべてのレイヤーをまとめて凍結することができます。
BatchNormalization レイヤーに関する重要な注意事項
多くのモデルには tf.keras.layers.BatchNormalization
レイヤーが含まれています。このレイヤーは特殊なケースで、ファインチューニングのコンテキストに注意を払う必要があります。このチュートリアルでも後ほど説明します。
layer.trainable = False
と設定する場合、BatchNormalization
レイヤーは推論モードで実行されるため、その平均と分散統計は更新されません。
ファインチューニングを行うために BatchNormalization(バッチ正規化)レイヤーを含んだモデルを解凍する場合には、基本モデルを呼び出す際に training = False
を渡して BatchNormalization レイヤーを推論モードにしておく必要があります。そうしないと、トレーニング不可能な重みに更新が適用され、モデルが学習したものを破壊してしまいます。
詳細については、転移学習ガイドをご覧ください。
分類ヘッドを追加する
特徴ブロックから予測値を生成するには、f.keras.layers.GlobalAveragePooling2D
レイヤーを使用して 5x5
空間の空間位置を平均化し、特徴を画像ごとに単一の1280要素ベクトルに変換します。
tf.keras.layers.Dense
レイヤーを適用して、これらの特徴を画像ごとに単一の予測値に変換します。この予測は logit
または未加工の予測値として扱われるため、ここで活性化関数は必要ありません。 正の数はクラス 1 を予測し、負の数はクラス 0 を予測します。
Keras Functional API を使用して、データ増強、リスケール、base_model、特徴抽出レイヤーを連結してモデルを構築します。前に触れたように、モデルには BatchNormalization レイヤーが含まれているため、training=False を使用します。
MobileNet の 800 万個以上のパラメータは凍結されていますが、Dense レイヤーには 1200 個のトレーニング可能なパラメータがあります。これらは 2 つの tf.Variable
オブジェクトである、重みとバイアスに分割されます。
モデルをコンパイルする
トレーニングする前にモデルをコンパイルします。2 つのクラスがあり、モデルが線形出力を提供するので、from_logits=True
で tf.keras.losses.BinaryCrossentropy
を使用します。
モデルをトレーニングする
10 エポックのトレーニング後は、検証セットの精度が最大 96%になります。
学習曲線
MobileNet V2 基本モデルを固定の特徴抽出器として使用する場合の、トレーニングと検証それぞれの精度と損失の学習曲線を見てみましょう。
注意: 明らかに検証指標がトレーニング指標よりも優れていることを疑問に思われるかもしれませんが、それはトレーニング中に tf.keras.layer.BatchNormalization
や tf.keras.layer.Dropout
などのレイヤーが精度に影響を与えていることが主な要因です。検証損失の計算時には、これらのレイヤーはオフになっています。
また、上記の要因ほどではないにせよトレーニング指標がエポックの平均を報告する一方で検証指標がエポック後に評価されるため、検証指標の方が少しだけ長い時間トレーニングされたモデルを参照しているという理由もあります。
ファインチューニング
特徴抽出の実験では、MobileNet V2 基本モデル上に少数のレイヤーを重ねてトレーニングをしたに過ぎませんでした。事前トレーニング済みネットワークの重みはトレーニング中に更新されません。
パフォーマンスをさらに向上させる方法の 1 つに、追加した分類器のトレーニングと並行して、事前トレーニング済みモデルの最上位レイヤーの重みをトレーニング(または「ファインチューニング」)するというものがあります。トレーニングのプロセスでは、一般的な特徴マップから特にデータセットに関連付けられた特徴に、強制的に重みをチューニングします。
注意: これは必ず、事前トレーニング済みモデルをトレーニング不可に設定し、最上位の分類器をトレーニングした後に行うようにしてください。事前トレーニング済みモデルの上にランダムに初期化された分類器を追加してすべてのレイヤーを結合トレーニングしようとすると、(分類器からのランダムな重みにより)勾配の更新規模が大きすぎて、事前トレーニング済みモデルが学習したことを忘れてしまいます。
また、MobileNet モデル全体ではなく、少数の最上位レイヤーをファインチューニングしてみることをお勧めします。大部分の畳み込みネットワークでは、上位のレイヤーに行くほど専門性が高くなります。最初の数レイヤーは、ほとんどすべてのタイプの画像に一般化する、非常に単純かつ一般的な特徴を学習します。上位のレイヤーに行くに従って、特徴はモデルがトレーニングされたデータセットに対してもっと固有なものになっていきます。ファインチューニングの目的は、一般的な学習を上書きするのではなく、これらの特殊な特徴に適応させて新しいデータセットで作業ができるようにすることです。
モデルの最上位レイヤーを解凍する
ここでは base_model
を解凍して、最下位レイヤーをトレーニング不可設定にするだけです。その後、モデルを再コンパイルして(これは行った変更を有効化するために必要)、トレーニングを再開します。
モデルをコンパイルする
かなり大規模なモデルをトレーニングしているため、事前トレーニング済みの重みを再適用する場合は、この段階では低い学習率を使用することが重要です。そうしなければ、モデルがすぐに過適合を起こす可能性があります。
モデルのトレーニングを続ける
前に収束するようにトレーニングをした場合は、このステップを踏むと精度が数ポイント向上します。
MobileNet V2 基本モデルの最後の数レイヤーをファインチューニングし、その上で分類器をトレーニングした場合の、トレーニングと検証それぞれの精度と損失の学習曲線を見てみましょう。検証損失の曲線がトレーニング損失よりもはるかに高いため、多少の過適合が発生する可能性があります。
また、新しいトレーニングセットが比較的小規模で、元の MobileNet V2 データセットに似ているために、過適合が発生する場合があります。
モデルをファインチューニングした後は、検証セットの精度はほぼ 98%に達します。
評価と予測をする
最後に、テストセットを使用して、新しいデータでモデルの性能を検証することができます。
これで、このモデルを使用してペットが猫か犬かを予測する準備がすべて整いました。
要約
特徴抽出に事前トレーニング済みモデルを使用する: 小さなデータセットで作業する場合は、より大規模な同じドメインのデータセットでトレーニングされたモデルが学習した特徴を利用するのが一般的です。これは、事前トレーニング済みモデルをインスタンス化し、その上に完全に接続された分類器を追加して行います。事前トレーニング済みモデルは「凍結」されているため、トレーニング中は分類器の重みだけを更新します。この場合、畳み込みベースは各画像に関連付けられたすべての特徴を抽出し、抽出された特徴量のセットから画像クラスを決定する分類器をトレーニングします。
事前トレーニング済みモデルをファインチューニングする: 性能をさらに向上させるために、事前トレーニング済みモデルの最上位レイヤーをファインチューニングして、新しいデータセットに再利用することができます。この場合は、データセット固有の高レベルの特徴をモデルが学習するように重みをチューニングします。この手法は、通常はトレーニングデータセットが大規模で、事前トレーニング済みモデルがトレーニングされた元のデータセットによく似ている場合に推奨されます。
さらに詳しくは転移学習ガイドをご覧ください。