Fast AI 2018 Lesson 2

講義資料

  • 講義動画 

Deep Learning For Coders—36 hours of lessons for free

  • 対応ノート(Kernel)

fast.ai lesson 1 | Kaggle

学んだこと

モデル学習時のテクニック

FineTuning

既存の学習済みのモデルを元に新たなモデルを構築する手法。今回の講義の構築するモデルの肝。 既存のモデルの最後の層以外の重みを固定して、最後の層の重みのみを新たなデータセットで学習する。 f:id:daikonclover:20181222210014p:plain

利点
  • 一から学習する場合と比べて、学習データが少なくても精度のよいモデルを作れる可能性がある
  • 学習データが少ない && 学習層が少ないので、学習に時間がかからない
欠点
  • 新たに学習するデータと元のモデルに使われた学習データがあまりにもかけ離れていると、効果は得られない可能性が高い。

うまくいく例

元の学習データ: 人の手で取った写真(ライオン、キリン)

新たに入力するデータ: 人の手で取った写真(犬、猫)

うまくいかない例

元の学習データ: CTスキャンの画像

新たに入力するデータ: 人の手で取った写真(犬、猫)

なぜこの手法が成立するのか?

高次の層にいくにつれて、画像の具体的な部分を学習するようになるが、 低次の層は、どの画像にも共通するような要素を学習しているので、使い回しが可能だから、とのこと。

f:id:daikonclover:20181222210942p:plain
低レイヤー: どの画像にも共通する部分を学習(物体の縁?)
f:id:daikonclover:20181222211127p:plain
高レイヤー: ある画像の具体的な部位を学習(再利用性は低い)

最適なLearning Rateの決定方法

Learning Rateは小さすぎると学習が終わらないが、大きすぎても発散してしまうので、適切な値を見つける必要がある。fast aiのライブラリのlr_findを用いることで最適な値を得ることができる。 この値は、loss値をlearning rateで微分した値が最小となる値を指す。

f:id:daikonclover:20181222211646p:plain
この場合は、接戦の負の傾きが最大になっている10^-2付近が最適な学習率となる

Learning Rateを学習時に動的に変更する

上記の方法で効率のよい学習率を見つけることはできるが、どうしても学習が進んでいくと、後半は値が収束しなくなってしまう。 より正確な重みの値を得るためには、局所解に近づくにつれ徐々に学習率を小さくしていきたい、という発想になる。

cos アニーリング

先程の方法で見つけた値を初期値として、学習を進めるにつれて、cos関数に従って徐々に値を減らしていく。 f:id:daikonclover:20181222213441p:plain

リスタート

より厳密な解を得やすくなったが、一度局所解の方向を見つけると、抜け出せなくなる可能性が高くなるということになる。これの問題点として、目的関数が以下のような場合、f:id:daikonclover:20181223054629p:plain

右側の谷底よりも左側の谷底の方がより優れた解であるといえる。 (異なるデータセットを投入して、例えばこのグラフが左右にずれた場合、右の解では最適な値でなくなってしまう、とのこと)

これは、定期的に減衰した学習率をリセットするとことで右側のような局所解にはまる可能性を減らすことができる。 リセットするタイミングは1つ、またはいくつかのエポックが終わる毎でよい。

f:id:daikonclover:20181222213254p:plain
各エポック毎にリセット
f:id:daikonclover:20181222213313p:plain
1エポック、3エポック、7エポック目が終わる度にリセット

Data Augmentation

学習用のデータを拡張(ここでは画像の反転、拡大・宿所、明るさの変更など)することによって、学習データを増やし、精度向上に役立てるというもの。 動画では、各エポック毎に拡張したデータを投入することで精度向上につながると紹介されていた。

f:id:daikonclover:20181222213524p:plain
左列: 1エポック目、中央: 2エポック目, 右列: 3エポック目

Differential Learning Rate

各層ごとに異なる学習率を採用する方法。 FineTuningで学習済みのモデルを元に新たな構築する際、 学習済みの低レイヤー層を固定するのではなく、高次のレイヤーと比べて小さい学習率を指定して再学習し、重みを微調整するのに用いられる。こうすることで、層を固定した場合よりも高い精度が得られる。

学習率は後ろの層にいくにつれて、3-10倍になっていくように設計するとよい。

eg.) 1層目: 10 ^ -4, 2層目: 10 ^ -3, 3層目: 10 ^ -2

推論時のテクニック

構築済みのモデルに変更を加えずに、推論時に工夫を加えることによって精度を上げる

TTA (TestTimeAugumentation)

モデルに入力画像を投入する前に、Data Augumentationを行い、拡張後のデータそれぞれを推論し、それらの平均を出力とする方法。1枚の画像の場合と比べて、出力が安定する可能性がある。簡単な手法だが、結構効果があるそう。

fast aiのライブラリにはTTAを行うためのメソッドが用意されている

# learnは学習済みのモデルのオブジェクト
log_preds, y = learn.TTA()

TTAなしの場合

入力(判別したい画像)→モデル→推論値(出力)

TTAありの場合

入力(判別したい画像)→拡張データ [入力1,入力2, ..., 入力n] → モデル→ [推論値1, 推論値2, 推論値n] → 推論値の平均(出力)

分析時のテクニック

Confusion Matrix

実際のラベル(縦軸)が推論時にどのラベル(横軸)に分類されたかをひと目で判断できる。対角線上の値が正しく分類できた場合の数。 f:id:daikonclover:20181222201526p:plain

State of the artの画像判別モデルの構築手順

上記のテクニックを駆使することで簡単に高精度のモデルを構築できる。 以下は今回の講義で紹介されていた方法のまとめ。

1 既存のモデルをベースに、最後の層のみ学習を行う。

arch=resnet34 # ベースとなるモデル
sz = 224 # 画像のサイズ
# データ拡張を行うための記述
tfms = tfms_from_model(resnet34, sz, aug_tfms=transforms_side_on, max_zoom=1.1)
data = ImageClassifierData.from_paths(PATH, tfms=tfms)
 # precompute = Trueで最後の層以外を固定
learn = ConvLearner.pretrained(arch, data, precompute=True)

#最適な学習率の初期値を計算
lrf=learn.lr_find()

#学習(エポック数は2-3でよい)
# cycle_lenはエポック毎にアニーリングとリスタートをするためのパラメータ
learn.fit(1e-2, 2, cycle_len=1)

2 仕上げとして低レイヤー層を固定化せず、全層を学習しなおす

#固定を解除
learn.unfreeze()
# Differential Leaning Rate
diff_lr=np.array([1e-4, 1e-3, 1e-2])
learn.fit(diff_lr, 3, cycle_len=1)