- データの前処理は大事
- データオーギュメンテーションを行わないと過学習しまくる
- 加工がキツ過ぎても汎化性能は落ちる(上下反転、色を極端にいじるなど)
- MaxPoolはストライド幅2の畳み込みで代用できる
- 浅いネットワークではMaxPoolを全て置き換えても性能はほとんど落ちないが、深くなるとパラメータが収束しなくなる
- したがって深いネットワークではMaxPoolを先頭に1つ挟む必要がある
- なぜMaxPoolを入れると収束するのかはわからない(MaxPoolは最大出力をもつノード以外のノードに対する勾配の伝達をせき止めるから?)
- 重みの初期化は大事(ハマりポイント)
- 浅いときは初期化せずとも収束するが、深くなるほど勾配が爆発しやすくなる
- 学習が早くなる
- 学習が十分に進行するには一定のイテレーション数と学習率が必要
- イテレーション数(バッチ数xエポック数)が足りなければ、そもそも重みが最適解まで移動できない
- 学習率が低ければ、局所最適解に留まる可能性が高まる
- バッチサイズとイテレーション数は反比例するので、イテレーション数を保つ場合は、バッチサイズとエポック数は同じ割合で変化させる
- バッチ正規化層にはレイヤ正規化層とは異なり、バッチサイズというメタパラメータが直接影響してくるので注意が必要
- 使用する場合はバッチサイズについて再検討する必要がある
- バッチ正規化はバッチサイズを小さくすることで効果を発揮する(バッチサイズを小さくするほど、バッチごとの分布に差が生じる)
- バッチサイズを減らすと学習・推論が遅くなるというデメリットがある
- データオーギュメンテーション(前処理)
- 最低限のモデルサイズ(深くしたいなら残差結合、重みの初期化は必須)
- ハイパーパラメータの調整
- 学習率の逐次調整
- イテレーション数
- まずはナイーブなモデルを構築する
- 訓練誤差やテスト誤差などから性能を検証できるようにする
- 簡単にメタパラメータを弄って比較し、そのモデルから最大の性能を引き出すようなメタパラメータを見つけ、それをベースモデルとする
- 層を深くするなど、モデルのアーキテクチャを変更する場合は、このベースモデルを超える性能を出せなければならないので、それがモデル設計におけるひとつの指針になる
- ベースモデルを超える性能をもつモデルが構築できたら、最大の性能を引き出すメタパラメータを探索して、新たなベースモデルとする
- 以下ループ
CIFAR10データセットを用いて、実際に上の指針に沿ってモデルをフルスクラッチで構築するということをやったので、それらを手順ごとに解説していきます
これを読むことで画像分類モデルに使われている各種モジュールがどのような役割を果たしているのか、そして採用されたメタパラメータの妥当性について、俯瞰的に理解することができるようになります
以下の手順では前提として、上のノウハウのうち、初めからあるに越したことがないものは予め仮定してしまいます
それは
- データオーギュメンテーション
- 重みの初期化
- 学習率の逐次調整(開始時は0.01、半分に達したら0.001、4分の3に達したら0.0001に変更)
の3つです
これをやっておかないと、過学習が起きたり、モデルの学習がうまく収束しなかったり、学習の進みが遅かったり、モデルを構築・比較検証していく上で良くないことしか起こりません
なお、以下の図で学習時間の半分に達したところでグラフが不連続になって性能が上がっているのは、3の学習率を下げたことに起因するものです
まずは、画像分類モデルに必要となるモデルのミニマルな構成を行っていきます
これは c52e21a で行いました
畳み込み層と非線形関数(ReLU)、MaxPool層というサンドウィッチ構造を2回重ねただけの非常にシンプルなものです
各レイヤの意味については、すでに様々なところで解説されているのでそこを参照してください
使用ライブラリであるpytorchにおける仕様は以下の通りです
- https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html
- https://pytorch.org/docs/stable/generated/torch.nn.ReLU.html
- https://pytorch.org/docs/stable/generated/torch.nn.MaxPool2d.html
大事なのは小難しい解釈というより、とりあえずこれを使えば最低限の性能が出るということです
CIFAR10は10種類の画像を分類するものなので、最悪のケースで10%の性能が出ます(0%ではありません)
したがって最低限の性能というのは、ここでは正答率10%以上の性能がでるということを意味します
ということで、実際に実行してみた結果が以下の図です
図では正答率ではなく誤り率をプロットしているので上下逆さになっていて見にくいですが、学習データが含まれていない検証用のデータセットに対して63%ぐらいの正答率を叩き出しています
こんなシンプルなモデルで6割も正解できるのはすごいですね!
また、訓練誤差よりも検証誤差のほうが小さくなっており、汎化性能が高いことが特筆すべき点です
これが良いことなのかどうかはよくわかりません 上手く学習されているモデルには一般的に起こる現象なんでしょうか? 理由を知っている人がいれば教えてください
前提として掲げたデータオーギュメンテーションを行ったおかげで、過学習も起こっていません
過学習が起こっている場合、訓練誤差が減少し続ける一方で、検証誤差が上に反り返るという振る舞いが観測できます
訓練データセットと検証データセットの2つを用意し、訓練誤差と検証誤差の両方を比較できるようにした理由は、このように過学習や汎化性能の有無などを判定することで、モデルの効果的な構築に向けた指針にできるからです
ということでつぎはこのナイーブなモデルに対して、最も性能と引き出すことのできるメタパラメータを見つけます
ここで探索するメタパラメータはバッチサイズです
モデルの訓練方法にはミニバッチ学習というものを採用しているので、1バッチにつきいくつの学習データサンプルを含めるかによって、学習の安定性が変わります