# ディープラーニングのトレーニングテクニック ニューラルネットワークが深くなるにつれて、そのトレーニングプロセスはますます難しくなります。主な問題の1つは、いわゆる[消失勾配](https://en.wikipedia.org/wiki/Vanishing_gradient_problem)または[爆発勾配](https://deepai.org/machine-learning-glossary-and-terms/exploding-gradient-problem#:~:text=Exploding%20gradients%20are%20a%20problem,updates%20are%20small%20and%20controlled.)です。[この投稿](https://towardsdatascience.com/the-vanishing-exploding-gradient-problem-in-deep-neural-networks-191358470c11)は、これらの問題についての良い紹介を提供しています。 深いネットワークのトレーニングをより効率的にするために、いくつかのテクニックを使用できます。 ## 値を適切な範囲に保つ 数値計算をより安定させるために、ニューラルネットワーク内のすべての値が通常[-1..1]または[0..1]の範囲内にあることを確認したいです。これは非常に厳しい要件ではありませんが、浮動小数点計算の性質上、異なる大きさの値を正確に一緒に操作することはできません。たとえば、10-10と1010を加算すると、1010が得られる可能性が高く、より小さな値は大きな値と同じオーダーに「変換」され、その結果、仮数部が失われます。 ほとんどの活性化関数は[-1..1]の周りに非線形性を持っているため、すべての入力データを[-1..1]または[0..1]の範囲にスケールすることは理にかなっています。 ## 初期重みの初期化 理想的には、ネットワークの層を通過した後に値が同じ範囲にあることを望みます。したがって、値の分布を保持するように重みを初期化することが重要です。 正規分布**N(0,1)**は良いアイデアではありません。なぜなら、*n*個の入力がある場合、出力の標準偏差は*n*になり、値が[0..1]の範囲から外れる可能性が高くなるからです。 以下の初期化方法がよく使用されます: * 一様分布 -- `uniform` * **N(0,1/n)** -- `gaussian` * **N(0,1/√n_in)**は、平均がゼロで標準偏差が1の入力に対して同じ平均/標準偏差を保持することを保証します * **N(0,√2/(n_in+n_out))** -- いわゆる**Xavier初期化**(`glorot`)は、信号を前向きおよび後ろ向きの伝播中に範囲内に保つのに役立ちます ## バッチ正規化 適切な重みの初期化があっても、トレーニング中に重みが任意に大きくなったり小さくなったりすることがあり、それによって信号が適切な範囲から外れることがあります。**正規化**テクニックの1つを使用することで、信号を戻すことができます。いくつかの方法があります(重みの正規化、層の正規化)が、最もよく使用されるのはバッチ正規化です。 **バッチ正規化**のアイデアは、ミニバッチ全体のすべての値を考慮し、これらの値に基づいて正規化(すなわち、平均を引き、標準偏差で割る)を行うことです。これは、重みを適用した後、活性化関数の前にこの正規化を行うネットワーク層として実装されます。その結果、最終的な精度が高くなり、トレーニングが速くなることが期待できます。 こちらがバッチ正規化に関する[元の論文](https://arxiv.org/pdf/1502.03167.pdf)、[Wikipediaの説明](https://en.wikipedia.org/wiki/Batch_normalization)、および[良い入門ブログ投稿](https://towardsdatascience.com/batch-normalization-in-3-levels-of-understanding-14c2da90a338)(ロシア語のもの[こちら](https://habrahabr.ru/post/309302/))です。 ## ドロップアウト **ドロップアウト**は、トレーニング中にランダムなニューロンの一定割合を削除する興味深いテクニックです。これは、削除するニューロンの割合(通常10%〜50%)という1つのパラメータを持つ層として実装され、トレーニング中に入力ベクトルのランダムな要素をゼロにし、次の層に渡します。 これは奇妙なアイデアのように思えるかもしれませんが、MNIST数字分類器のトレーニングにおけるドロップアウトの効果を[`Dropout.ipynb`](../../../../../lessons/4-ComputerVision/08-TransferLearning/Dropout.ipynb)ノートブックで見ることができます。これはトレーニングを加速し、より少ないエポックで高い精度を達成することを可能にします。 この効果はいくつかの方法で説明できます: * モデルに対するランダムなショック要因と見なすことができ、最適化が局所最小値から外れることを助けます * ドロップアウト中にわずかに異なるモデルをトレーニングしていると考えることができるため、*暗黙のモデル平均化*として見なすことができます > *酔っ払った人が何かを学ぼうとすると、次の朝にはそれをよりよく覚えていると言う人もいます。これは、いくつかの故障したニューロンを持つ脳が意味を把握するためによりよく適応しようとするからだとされています。私たちはこれが真実かどうか自分たちでテストしたことはありません。* ## 過学習の防止 ディープラーニングの非常に重要な側面の1つは、[過学習](../../3-NeuralNetworks/05-Frameworks/Overfitting.md)を防ぐことができることです。非常に強力なニューラルネットワークモデルを使用したくなるかもしれませんが、モデルパラメータの数とトレーニングサンプルの数を常にバランスさせるべきです。 > 以前に紹介した[過学習](../../3-NeuralNetworks/05-Frameworks/Overfitting.md)の概念を理解していることを確認してください! 過学習を防ぐ方法はいくつかあります: * 早期停止 -- 検証セットのエラーを継続的に監視し、検証エラーが増加し始めたらトレーニングを停止します。 * 明示的な重みの減衰 / 正則化 -- 高い絶対値の重みに対して損失関数に追加のペナルティを加えることで、モデルが非常に不安定な結果を得るのを防ぎます * モデル平均化 -- 複数のモデルをトレーニングし、その結果を平均化します。これにより、分散を最小限に抑えることができます。 * ドロップアウト(暗黙のモデル平均化) ## 最適化アルゴリズム / トレーニングアルゴリズム トレーニングのもう1つの重要な側面は、良いトレーニングアルゴリズムを選ぶことです。古典的な**勾配降下法**は合理的な選択ですが、時には遅すぎたり、他の問題を引き起こしたりすることがあります。 ディープラーニングでは、**確率的勾配降下法**(SGD)を使用します。これは、トレーニングセットからランダムに選択されたミニバッチに適用された勾配降下法です。重みはこの式を使用して調整されます: wt+1 = wt - η∇ℒ ### モーメンタム **モーメンタムSGD**では、前のステップからの勾配の一部を保持します。これは、どこかに慣性を持って移動しているときに、異なる方向にパンチを受けたときに、軌道がすぐに変わらず、元の動きの一部を保持するのに似ています。ここで、*速度*を表す別のベクトルvを導入します: * vt+1 = γ vt - η∇ℒ * wt+1 = wt+vt+1 ここで、パラメータγは、慣性を考慮する程度を示します:γ=0は古典的なSGDに対応し、γ=1は純粋な運動方程式です。 ### Adam、Adagradなど 各層で信号をいくつかの行列Wiで掛け算するため、勾配は減少して0に近づくか、無限に増加することがあります。これは、爆発/消失勾配問題の本質です。 この問題の解決策の1つは、方程式で勾配の方向のみを使用し、絶対値を無視することです。すなわち、 wt+1 = wt - η(∇ℒ/||∇ℒ||)、ここで||∇ℒ|| = √∑(∇ℒ)2 このアルゴリズムは**Adagrad**と呼ばれます。同じアイデアを使用する別のアルゴリズムには、**RMSProp**、**Adam**があります。 > **Adam**は多くのアプリケーションにとって非常に効率的なアルゴリズムと見なされているため、どれを使用するかわからない場合は、Adamを使用してください。 ### 勾配クリッピング 勾配クリッピングは、上記のアイデアの拡張です。||∇ℒ|| ≤ θのとき、重みの最適化において元の勾配を考慮し、||∇ℒ|| > θのときは勾配をそのノルムで割ります。ここでθはパラメータであり、ほとんどの場合、θ=1またはθ=10を選ぶことができます。 ### 学習率の減衰 トレーニングの成功は、学習率パラメータηに依存することがよくあります。ηの大きな値がトレーニングを速くすることを想定するのは論理的であり、これは通常トレーニングの初期に望まれるもので、次に小さな値のηがネットワークを微調整するのを可能にします。したがって、ほとんどの場合、トレーニングの過程でηを減少させたいと思います。 これは、各エポックのトレーニング後にηを何らかの数(例えば0.98)で掛けるか、より複雑な**学習率スケジュール**を使用することで実現できます。 ## 異なるネットワークアーキテクチャ 問題に適したネットワークアーキテクチャを選択することは難しい場合があります。通常、特定のタスク(または類似のタスク)に対して実績のあるアーキテクチャを選びます。ここにコンピュータビジョンのためのニューラルネットワークアーキテクチャの[良い概要](https://www.topbots.com/a-brief-history-of-neural-network-architectures/)があります。 > トレーニングサンプルの数に対して十分な力を持つアーキテクチャを選択することが重要です。あまりにも強力なモデルを選択すると、[過学習](../../3-NeuralNetworks/05-Frameworks/Overfitting.md)を引き起こす可能性があります。 もう1つの良い方法は、必要な複雑さに自動的に調整されるアーキテクチャを使用することです。ある程度、**ResNet**アーキテクチャと**Inception**は自己調整型です。[コンピュータビジョンアーキテクチャに関する詳細](../07-ConvNets/CNN_Architectures.md)をご覧ください。 **免責事項**: この文書は、機械ベースのAI翻訳サービスを使用して翻訳されています。正確性を追求していますが、自動翻訳には誤りや不正確さが含まれる可能性があることをご理解ください。原文の母国語の文書が権威ある情報源と見なされるべきです。重要な情報については、専門の人間翻訳をお勧めします。この翻訳の使用によって生じた誤解や誤訳に対して、当社は責任を負いません。