Google Researchの神資料を読み解いてみる①【Deep Learning Tuning Playbook】

# はじめに
研究しなきゃなのはわかってるが何から始めればいいんだ、とりあえずでモデル組んだけどまともに動かん。なにがダメなのか分からねぇ、どこをどういじれば何がどう変わるんだ、、、と日々悲鳴をあげている中、Google Researchの研究者による、Deep Learning Tuning Playbook（ https://github.com/google-research/tuning_playbook ）が公開されました。

どうやら深層学習ネットワークをチューニングする際の考え方やら注意点を、Googleの神たちがまとめてくださっているようです。これは読んでおこうと思い、自分の読解とメモついでに和訳してみることにしました。

【注意】
翻訳アプリそのままではなく、一応多少自分なりに解釈して理解したいということで、一部抜けてたり言い回しが違ったり、そのまんま和訳になっているとは限りません（要約してるわけでもない）。また、深層学習も英語もナンモワカランなので訳や解釈が間違っている可能性も十分あります。正確に知りたい方はどうぞ原文をお読みください。
つよつよな皆様におかれましては、なんかココおかしいだろ等あれば教えていただければ幸いです。

# 目次

コチラが本家のTable of Contentsですが、やってみたら思ったよりも長かったため今回は途中まで。力尽きなければ続きは別の投稿としてあげる予定です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310255/0493872c-4dcf-f6af-ce03-feade7d98f1c.png)

-   [Who is this document for?](#1-who-is-this-document-for)
-   [Why a tuning playbook?](#2-why-a-tuning-playbook)
-   [Guide for starting a new project](#3-guide-for-starting-a-new-project)
    -   [Choosing the model architecture](#choosing-a-model-architecture)
    -   [Choosing the optimizer](#choosing-the-optimizer)
    -   [Choosing the batch size](#choosing-the-batch-size)
    -   [Choosing the initial configuration](#choosing-the-initial-configuration)

では、本編へどうぞ。


# 1. Who is this document for?

- 機械学習のパフォーマンスを最大化したいすべてのエンジニアとリサーチャーに向けて。
    - 機械学習/深層学習における基本知識を習得していることを前提としている。
- ハイパーパラメータのチューンニングを中心に、パイプラインの実装やOptimizationについても軽く述べる。
- 機械学習問題は教師アリ学習（または自己教師学習など類似の問題）だと仮定する。
    - とはいえ、他のタイプの問題にも適応できる可能性はある。

# 2. Why a tuning playbook?

- DNNを実際に機能させるためには、非常に多くの労力がかかる
- しかも、良い結果を得るためのノウハウがほとんどドキュメント化されていない
    - 論文では、ストーリーを明確にするために、良い結果が現れるまでの過程は細かく触れられない
    - 商業用途で研究を行う機械学習エンジニアには、一歩下がってプロセスを一般化する時間はない。
    - 教科書の類では、実用的なアドバイスよりも基礎的な理論の説明が優先される。
- このドキュメントの作成にあたり、深層学習で良い結果を得るための手法について、包括的に説明した過去の事例は見つからなかった。
    - その代わり、ブログやソーシャルメディア、論文の付録などで、断片的なアドバイスや、特定の状況下における事例などが散らばっており、混乱が見受けられた。
- たとえ表面上似たメソッドを使用しても、熟練した専門家がやるのと、未熟な初心者がやるのとでは、深層学習で得られる結果には大きな違いがある。
- と同時に、専門家たちは、そのやり方が完全に正しいとは限らないことも知っている。
- 深層学習が世界に与える影響が大きくなる中、深層学習で良い結果を得るための実用的なディティールを含んだレシピが必要である。

 ---

- このドキュメントの著者は、深層学習に熟練した5人の研究者およびエンジニア
    - 早くは2006年から、あらゆる問題に対して深層学習を適用する研究をしてきた。
- このドキュメントは、そんな著者たちが同僚や新米エンジニアにアドバイスする経験から生まれたもの。
- 深層学習が一握りの学術研究所で行われてきた機械学習手法から、何十億もの人々が使う製品に力を与える技術になったことは非常に喜ばしいことだが、深層学習は工学分野としてはまだまだ初期段階にある。
- このドキュメントが、深層学習分野の体系化の一助になればと思っている。

---

- このドキュメントは深層学習に対する筆者らのアプローチを結晶化しようとする試みの産物であり、客観的事実ではなく、筆者らの当時の考えをまとめたものである。
- パラメータチューニングは、筆者ら自身も苦労したため、特に重点を置いて述べるが、筆者らが遭遇し、あるいは失敗を目の当たりにした、その他の問題についても取り上げる。
- このドキュメントは、自分たちの考えの変化に伴い、生きたドキュメントとしてどんどん進化していくことを想定している。
    - 新しい結果やワークフローの改善を考慮すれば、必然的にアドバイスの一部を更新することになる。
- 筆者らも現時点で、深層学習の理想的なレシピを知っているわけではない
    - しかし、文書化や議論を進めないことには、それを見つけ出すことは出来ない。
- そこで、読者らにも、この文書に問題点を見つけたら、説得力のある証拠と共に改善案を提示してほしい。
    - そうすることで、文書をよりよく更新することが出来る。
- コミュニティとして最適解を見つけ出すためにも、この文書以外のガイドやPlaybookが生まれていくことも期待している。
- 文書中で、ロボットの絵文字（🤖）がある部分は、より詳細な調査を必要とする部分。
    - この文書を書いてみて初めて、いかに多くの興味深い研究課題や、放置されている研究課題があるかが明らかになった。

# 3. Guide for starting a new project

**チューニングの過程で行う多くの決定は、プロジェクトの最初に一度だけ行い、状況が変化したときに時折見直すだけで良い。**

- 以下のような状況を前提として述べる。
    - 問題の設定、データのクリーニングなどの基本的な作業はすでに十分に行われており、モデルアーキテクチャの選定や学習の設定に時間をかけることが有意義である。
    - 学習と評価のパイプラインが既に設定されており、試してみたい様々なモデル条件での学習/推論を簡単に実行できる。
    - 適切な評価基準が選択/実装されている。
        - その評価基準は、環境で測定されるものを可能な限り代表するものである。
        
## Choosing the model architecture

**プロジェクトを始める際には、すでにうまく動いているモデルを再利用するべし。**

- 初めにまともに動作させるために、すでに確立され一般に使用されているモデルアーキテクチャを選択すること。
    - カスタムモデルを後から構築することはいつでも出来る。
- モデルアーキテクチャは普通、モデルの大きさやその他の詳細な設定を決定する様々なハイパーパラメータ(層の数や幅、活性化関数の種類等)を持っている。
    - したがって、アーキテクチャを選定することは、実際には、ハイパラの設定ごとにひとつひとつ変わるモデルの系列を選ぶことである。
    - ハイパーパラメータの設定自体は別の項(Todo:link)で述べる。
- 可能な限り、扱う問題に出来るだけ似た問題に取り組んでいる論文を探し出し、再現することを出発点とする。

## Choosing the optimizer

**似たタイプの問題設定において、最もポピュラーなoptimizerから始めるべし**

- すべてのモデルや問題に対して"最適な" optimizerは存在せず、optimizerを比較するのは難しい。🤖
    - [comparing the performance of optimizers is a difficult task](https://arxiv.org/abs/1910.05446) 
- プロジェクトの初めには、一般に用いられ定評のあるoptimizerを使用することを推奨する。
    - 似たような問題でよく用いられているモノであると尚良い。
- optimizerの**全ての**パラメータに注意すること。
    - 多くのハイパーパラメータを持つoptimizerは、より多くのチューニングを必要とする場合が多い。
    - 特にプロジェクトの初期段階で、他の様々なハイパーパラメータをチューニングする際に、optimizerのハイパラが邪魔になるような場合がある。
    - より単純なoptimizerで始めて、あとからよりgeneralなoptimizerに切り替えることが望ましいかもしれない。
        - momentumを固定したSDGや、εやβを固定したAdamなど。
- 私たちがよく使用する"定評のあるoptimizer" とは
    - SDG with momentum（Nesterovの加速勾配降下法）
    - Adam及びNAdam
        - Adamは4つのハイパラを持ち、それらすべてが[結果に影響する](https://arxiv.org/abs/1910.05446)ので注意
        - Adamのハイパラチューニング(Todo:link)に関しての項も参照。


## Choosing the batch size

**バッチサイズは学習速度を制御するもので、モデルの性能を調整するためにチューニングすべきものではない。ハードでサポートされる最大のバッチサイズを使用すべし**

- バッチサイズは計算速度とコンピュータのリソース消費を決定付けるパラメータである。
- バッチサイズを増やすほど、計算時間は短くなる。バッチサイズを大きくする主な利点は以下。
    - 同じ時間でより多くのパラメータを試すことができ、最終的によりよいモデルを得られる可能性が高まる。
    - 開発サイクルの遅延を軽減し、新しいアイデアをより頻繁に試すことが出来る。
- バッチサイズを増やすことで、リソースの消費量は増加することも、減少することも、変わらないこともある。
- バッチサイズは、バリデーションセットにおけるパフォーマンス向上のためにチューニングされるべきではない
    - 他のすべてのハイパラ(特に学習率と正則化パラメタ)がきちんと調整され、十分な学習を行う場合、バッチサイズは最終的な結果に影響しない。
        - [Shallue et al. 2018](https://arxiv.org/abs/1811.03600)
        - [Why shouldn't the batch size be tuned to directly improve validation set performance?](https://github.com/google-research/tuning_playbook#why-shouldnt-the-batch-size-be-tuned-to-directly-improve-validation-set-performance)の項も参照

#### 実現可能なバッチサイズの決定とtraining throughputの見積もり

- バッチサイズは普通、アクセラレータのメモリによって制約がかかる。
    - 学習コード全体を実行することなくちょうどいいバッチサイズを計算するのは難しい。
    - メモリ超過を起こすまで、バッチサイズを変えながら少ないステップ数で学習全体を実行してみるのが良い。
        - たとえば2の累乗で
- 十分な時間学習を行うと、各バッチサイズでの、training throughput（1秒間に処理できるデータ数）の推定値を見積もることが出来る。
    - アクセラレータが飽和していない場合、バッチサイズが倍になると、training throughputも倍になる。
    - バッチサイズが大きくなっても、ステップあたりの処理時間はほぼ一定であるべき。
    - そうでない場合はI/Oや計算ノード間の同期などにボトルネックが存在すると考えられる
        - これらボトルネックは先に進む前に修正する価値があるかもしれない。
    - もし、あるバッチサイズまでしかtraining throughputが上がらないのであれば、それを超えるバッチサイズはサポートされていないと見做すべき。
        - バッチサイズを大きくするとtraining throughputが向上することが前提。そうでないならボトルネックを修正するか、より小さなバッチサイズを使用する。
        - 勾配累積(gradient accumulation)は、ハードウェアがサポートするよりも大きなバッチサイズをシミュレートするため、処理能力の点で利点は得られない。一般に、応用的な状況での利用は避けるべき。
- これらのステップは、モデルアーキテクチャやoptimizerを変更するたびに毎回繰り返す必要がある。
    - モデルアーキテクチャが異なれば、メモリサイズと合うバッチサイズも変わってくる。


#### 学習時間を最小化するためのバッチサイズの選定

- （総学習時間）＝（ステップあたりの学習時間）* （総ステップ数）
- 多くの場合、ステップあたりの学習時間はバッチサイズに関わらずほぼ一定
    - 並列計算が行われるため。前節で述べたボトルネックがある場合は例外。
    - 実際にはバッチサイズを大きくすることで、並列計算のオーバーヘッドがいくらか発生し多少遅くなる。
- バッチサイズを大きくすると、一定の性能に到達するために必要なステップ数は一般に減少する。
    - バッチサイズ変更に伴い、関連するハイパーパラメータが正しく調整されていることが条件（[Shallue et al. 2018](https://arxiv.org/abs/1811.03600)）
    - たとえば、バッチサイズを倍にすると、必要なステップ数は半分になる≒パーフェクトスケーリング
        - パーフェクトスケーリングは、Critical Batch Sizeまでの全てのバッチサイズで成立し、それを超えると効用が薄くなる。
        - 最終的には、バッチサイズを大きくしてもステップ数は変わらなくなる。
- したがって、総学習時間を最小化させるバッチサイズとは、ステップ数を削減できる最大化のバッチサイズである。
    - このバッチサイズは、データセットやモデル、optimizerに依存し、実験的に見つける以外の計算方法は確立していない🤖
- バッチサイズを比較する場合、example budgetやepoch budget(学習するサンプルの数を固定して全実験を行う場合の数の見積もり？)とstep budget(学習ステップ数を固定して全実験を行う場合のステップ数の見積もり？)の違いに注意する必要がある。
    - epoch budgetをバッチサイズと比較するのは、バッチサイズを大きくするとより学習ステップ数を減らして有意なスピードアップが出来る可能性があるにも関わらず、単にパーフェクトスケーリングが出来る領域を調べるだけになってしまう。（訳注：≒バッチサイズが増えると必要な総エポック数が減るわけじゃなくて総ステップ数が減るから、そこんところ混同しないでね、ってことだろうか。和訳がよくわからなかった。）
- 多くの場合、ハードウェアでサポートされる最大のバッチサイズがCritical Batch Sizeを下回るため、可能な限り大きなバッチサイズを用いればよい。
- バッチサイズを大きくしても、学習時間が長くなるのでは意味がない。学習時間を短くできるようにバッチサイズを変更するべき。

### リソースを最小化するためのバッチサイズの選定

- （訳注：バッチサイズ拡大と運用コスト見積もりの話で、学生の研究の範疇ではあんまり関係なさそうだったため省略）

### バッチサイズ変更によるハイパーパラメータの再調整

- ハイパーパラメータの最適値はバッチサイズによって変わる。
    - バッチサイズを変更すると、ハイパーパラメータチューニングをやり直す必要がある
- 特に、optimizerのハイパーパラメータ（学習率やモーメンタム）と正則化のハイパーパラメータが影響を受けやすいため、バッチサイズが変わるごとにチューニングする必要がある。
- プロジェクトの初めにバッチサイズを選定する際、このことを忘れてはならない。
    - あとからバッチサイズを変更すると、ハイパラの再チューニングに多大な時間と労力がかかる恐れがある。

### バッチ正則化とバッチサイズの関係

- バッチ正則化は複雑で、一般に、勾配計算とは異なるバッチサイズを使用して統計量を計算する必要がある。
    - 詳しくはバッチ正則化についての項（Todo:link）を参照。


## Choosing the initial configuration

- ハイパラチューニングを開始する前に、開始点を決める必要がある。
    - これには以下の指定も含まれる。
        - モデル構成（層の数など）
        - optimizerのハイパーパラメータ（学習率など）
        - 学習ステップ数
- これら初期設定の決定には、手動で設定した学習を実行し、試行錯誤する必要がある。
- ここでの方針は、"妥当な"結果を得るための、シンプルで、比較的速く、比較的リソース消費の少ない設定を見つけること。
    - シンプルとは、可能な限り装飾をなくし、あとから追加できるようにすること。たとえ将来的に役立つとわかっている設定でも、初期設定時に追加すると不必要に複雑化してしまう。
        - 例えば、学習率スケジューラを導入する前に、固定の学習率から始めること。
    - 高速で最小限のリソースで動く初期設定を利用することは、パラメータチューニングの効率化につながる。
    - "妥当な"結果とは、問題によって異なるが、学習したモデルがランダムよりもはるかに良い性能を発揮することを意味する。
- 学習ステップ数の選択には、以下のバランスを取ることが必要
    - ステップ数が増えると、性能が向上しチューニングが簡単になる
    - ステップ数が少なくなれば、より高速かつ省リソースで学習を行うことができ、より多くの実験を並列に行うことが出来る。
        - 過剰に多くのステップ数で学習を始めた場合、後で減らすことが難しいこともある
            - 学習率スケジューラがそのステップ数でチューニングされてしまった場合など。


# おわりに

【各種リンク】
本家 Deep Learning Tuning Playbook
https://github.com/google-research/tuning_playbook

パート①：Who is this document for?からGuide for starting a new projectまで
このページ。

パート②：A scientific approach to improving model performance の章
https://qiita.com/iykuetboo/items/bb57cc9d3f60c99f79b2

パート③以降：
いつか書きます。