@mizumotokのブログ

テクノロジー、投資、書評、映画、筋トレなどについて

転移学習の3つのシナリオとファインチューニングのコツ

転移学習は学習済みのモデルを別の分野に再利用することで、うまく使いこなすことは大きなアドバンテージになります。しかし、転移学習やファインチューニングは適用したい分野によって方法が異なります。できるだけ一般化したシナリオで、転移学習/ファインチューニングの方向性を決める方法が、スタンフォード大学機械学習の講義で紹介されていますので、まとめてみました。

f:id:mizumotok:20201118160017p:plain

転移学習とは

転移学習とは機械学習において、学習済みのモデルを別の分野に応用することです。ImageNetのような膨大なデータを使って学習するにはGPUリソース(時間)を多く使うので、これをショートカットできるのはありがたいことです。
フランス語を勉強するとそのノウハウがドイツ語の勉強にも活かせちゃう、感じですかね。

ファインチューニングとは

転移学習という言葉と一緒にファインチューニングという言葉もよく出てきます。
人によって言葉の定義は違ったりするのですが、私の解釈(定義)では、転移学習において学習済みのモデルの一部を使いたい分野に合うように再学習させることです。学習済みのモデルそのままではうまく精度ができない場合に、自分の持っているデータを使って再学習させます。その際に全部を再学習させると時間がかかったり、データが少ない場合は過学習の問題が起きたりすることに注意しないといけません。

転移学習やファインチューニングのシナリオ

学習済みのモデルの準備

Kerasのようなディープラーニングライブラリには多くの学習済みのモデルが用意されています。これらを使えばすぐに転移学習ができます。
もちろん自分で過去に作ったモデルを使うこともできます。

ImageNetで学習した重みをもつ画像分類のモデル

  • Xception
  • VGG16
  • VGG19
  • ResNet50
  • InceptionV3
  • InceptionResNetV2
  • MobileNet
  • DenseNet
  • NASNet
  • MobileNetV2

画像分類モデルの使用例

from keras.applications.resnet50 import ResNet50
from keras.preprocessing import image
from keras.applications.resnet50 import preprocess_input, decode_predictions
import numpy as np

model = ResNet50(weights='imagenet')

img_path = 'elephant.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

preds = model.predict(x)
# decode the results into a list of tuples (class, description, probability)
# (one such list for each sample in the batch)
print('Predicted:', decode_predictions(preds, top=3)[0])
# Predicted: [(u'n02504013', u'Indian_elephant', 0.82658225), (u'n01871265', u'tusker', 0.1122357), (u'n02504458', u'African_elephant', 0.061040461)]

上の例のように同じ分野に対しては、モデルをそのまま推論に使うことができます。

転移学習やファインチューニングのコツ

転移学習やファインチューニングをどう適用するかということについては、適用したい分野によって違う、としか言いようがありません。
機械学習初心者はここでつまづいてしまうのですが、スタンフォードの講義(Convolutional Neural Networks for Visual Recognition)の資料にわかりやすくガイドラインが示されています。

転移学習の3つのシナリオ

  • 特徴量抽出器として使う(特徴量で別の分類器を学習させる)
  • ファインチューニングして使う(再学習して重みを微調整する)
  • 公開された事前学習済みモデルを使う

ファインチューニングの4つのシナリオ

新しいデータセット 学習済みモデルの分野との関連 シナリオ
少ない 似ている 抽出された特徴量を線形分類器に学習させる
多い 似ている ネットワーク全体をファインチューニング(再学習)
少ない 異なる ネットワークの特定の層の活性化関数をSVM分類器に置き換えて学習させる
多い 異なる ネットワーク全体をファインチューニング(再学習)

転移学習(スタンフォード大学の講義資料より拙訳)

現実的に、十分な量のデータセットを持っていることはかなり珍しく、畳み込みニューラルネットワークを(ランダムな初期値を用いて)ゼロから学習させることは少ないです。
その代わりに、非常に大規模なデータセット(例えば、ImageNetの120万枚の画像と1,000のカテゴリ)でネットワークを事前に学習しておき、そのネットワークを初期化または目的のタスクのための特徴量抽出器として使用するのが一般的です。以下に転移学習の主要な3シナリオを示します。

  • 特徴量抽出機としてのネットワーク

ImageNetで事前学習したネットワークから最後のレイヤー(ImageNetでは1,000カテゴリのスコアを出力するが、目的のタスクでは異なる出力を得たい)を取り除き、残りのネットワークを新しいデータセットのための特徴量抽出器として使用します。AlexNetでは、分類器の直前の隠れ層での活性化計算を含めて、全画像に対して4,096次元のベクトル計算をします。これらの特徴量はCNNコードと呼ばれています。ImageNetのネットワーク学習中にしきい値があったら、これらのコードはReLU(つましきい値は0)であることがパフォーマンス上重要です。すべての画像の4,096次元のコードを抽出したら、新しいデータセットのための線形分類器(例えば,線形SVMやSoftmax分類器)を学習させます。

  • ファインチューニング

2番目の方法は、新しいデータセットで分類器を置き換えて再学習するだけでなく、誤差逆伝播法で学習済みのネットワークの重みを微調整します。ネットワークの全層をファインチューニングすることもできますし、(過学習の懸念があるので)最初の方の層を固定したまま上位層のいくつかをファインチューニングすることもできます。ネットワークの初期の層は多くのタスクに役立つはずの汎用的な特徴(エッジ検出やカラー検出など)を含んでいますが、それより後の層のは、元のデータセットに含まれているクラスの詳細に応じて、徐々に特定の特徴を持つようになるという観察結果に基づいています。多くの犬種を含むImageNetの場合、ネットワークにおける具象化のパワーの大部分が、犬種間の区別に特化した特徴に使われている可能性があります。

  • 事前学習済みモデル

最近の畳込みネットワークは、ImageNetで学習するのに、複数のGPUを使って2〜3週間かかります。そのため最終的なネットワークのチェックポイントを公開して、ファインチューニングできる人に使ってもらうのが一般的です。例えば、Caffeライブラリには、ネットワークの重みを共有するModel Zooがあります。

ファインチューニングいつどのように取り組めばよいか

新しいデータセットでどのような転移学習を行うべきかをどのやって決めればよいのでしょうか?これにはいくつかの要因が関係していますが、最も重要なのは、新しいデータセットのサイズ(小さいか大きいか)と、元のデータセットとの類似性(例えば、画像の内容や分類がImageNetに似ているか、顕微鏡画像のように非常に異なるか)の2つです。ネットワークの特徴は初期の層ではより一般的であり、後の層では元のデータセットに特化したものであることを念頭において、一般的な経験から4つのシナリオを導きました。

データセットが小さいと過学習の懸念があるため、ファインチューニングをするのは適切ではありません。データセットが元のデータセットに似ているので、ネットワークの上位レベルの特徴がこのデータセットにも関連していると予想されます。したがって、CNNコードで線形分類機を学習するのが最善の方法であるかもしれません。

多くのデータを持っているので、ファインチューニングをしても過学習の心配はありません。

データセットが小さいので、線形分類機だけを学習するのがベストかも知れません。また、データセットが非常に異なるので、データセット固有の特徴をより多く含むネットワークをそのまま使うのは適切ではありません。そのまま使う代わりに、ネットワークの初期の層の活性化関数にSVM分類器をつけて学習するほうがいいでしょう。

データセットが非常に大きいので、ゼロからネットワークを学習するのがよいと予想されるかもしれません。しかし、実際には、事前に学習したモデルの重みを用いて初期化することが役に立つことが多いです。この場合、ネットワーク全体をファインチューニングするのがよいでしょう。

実践的なアドバイス

転移学習をにはいくつかの注意点があります。

  • 事前学習済みモデルの制約

事前学習済みモデルを使う場合、新しいデータセットに使用できる構造に若干の制約があるかもしれません。例えば、事前学習されたネットワークから任意のConv層を取り除くことはできません。しかし、いくつかの変更は簡単です。パラメータを共有することで、異なる空間サイズの画像を使って事前学習済みネットワークを簡単に実行することができます。このことはConv/Poolでは明らかです。なぜなら、フォワード関数は入力ボリュームの空間サイズに依存しないからです(ストライドがフィットする限り)。FC層の場合もConv層に変換することができるので、同じことが言えます。例えば、AlexNetでは、最初のFC層の前の最終的なプーリングボリュームのサイズは[6x6x512]です。したがって、このボリュームを見ているFC層は、入力フィールドのサイズが6x6であり、パディングが0で適用されているConv層を有することと同等です。

  • 学習率

一般的には、新しいデータセットのスコアを計算する新しい(ランダムに初期化された)線形分類器の重みと比較して、ファインチューニングするネットワークの重みの学習率を小さくします。既存のネットワークの重みが比較的良いと予想されるため、(特に、新しい線形分類器がランダムな初期化から学習されている間に)あまり早くあまり多く歪ませたくないからです。

まとめ

  • 転移学習は学習済みのモデルを別の分野に応用することである
  • 転移学習では、分類器として使う、ファインチューニングする、公開された学習済みネットワークを見つけることを意識する
  • ファインチューニングはデータセットの大きさ、元のデータセットの関連性が適用の方法を判断するのに役に立つ

scikit-learnとTensorFlowによる実践機械学習

scikit-learnとTensorFlowによる実践機械学習

  • 作者:Aurélien Géron
  • 発売日: 2018/04/26
  • メディア: 単行本(ソフトカバー)