PyTorch | ニューラル ネットワークのトレーニングを最適化する 17 の方法

PyTorch | ニューラル ネットワークのトレーニングを最適化する 17 の方法

[[442468]]

この記事では、PyTorch を使用して深層モデルをトレーニングするための最も労力を節約し、効果的な 17 の方法を紹介します。この記事で説明する方法はすべて、GPU 環境でモデルをトレーニングすることを前提としています。具体的な内容は以下のとおりです。

01. 学習率スケジュールの変更を検討する

学習率スケジュールの選択は、モデルの収束速度と一般化能力に大きな影響を与えます。 Leslie N. Smith らは、論文「ニューラル ネットワークのトレーニングのための巡回学習率」および「スーパー コンバージェンス: 大きな学習率を使用したニューラル ネットワークの非常に高速なトレーニング」で、巡回学習率と 1 サイクル学習率スケジュールを提案しました。これは後に fast.ai の Jeremy Howard 氏と Sylvain Gugger 氏によって普及されました。次の図は、1 サイクル学習率スケジュールの図です。

Sylvain 氏は次のように書いています: 1Cycle は、同じ長さの 2 つのステップで構成されます。1 つは、低い学習率から高い学習率へのステップで、もう 1 つは最低レベルに戻るステップです。最大値は学習率ファインダーによって選択された値から取得され、値が小さい場合は 10 分の 1 になることがあります。次に、このサイクルの長さはエポックの総数よりもわずかに小さくする必要があり、トレーニングの後期段階では、学習率が最小値よりも数桁小さくなるようにする必要があります。

最良の場合、このスケジュールは従来の学習率スケジュールと比較して大幅な高速化(スミスはこれをスーパーコンバージェンスと呼んでいます)を実現します。たとえば、ImageNet データセットで ResNet-56 をトレーニングするために 1Cycle 戦略を使用すると、トレーニングの反復回数は元の 1/10 に削減されますが、モデルのパフォーマンスは元の論文のレベルと依然として同等です。一般的なアーキテクチャとオプティマイザーでは、このスケジュールはうまく機能するようです。

Pytorch は、「torch.optim.lr_scheduler.CyclicLR」と「torch.optim.lr_scheduler.OneCycleLR」という 2 つのメソッドを実装しています。

参照ドキュメント: https://pytorch.org/docs/stable/optim.html

02. DataLoader で複数のワーカーとページロックされたメモリを使用する

torch.utils.data.DataLoader を使用する場合は、デフォルト値の 0 ではなく num_workers > 0 を設定し、デフォルト値の False ではなく pin_memory=True を設定します。

参照ドキュメント: https://pytorch.org/docs/stable/data.html

NVIDIA のシニア CUDA ディープラーニング アルゴリズム ソフトウェア エンジニアである Szymon Micacz 氏は、4 つのワーカーとページロックされたメモリを使用して、1 つのエポックで 2 倍の高速化を達成したことがあります。ワーカーの数を選択する際によく使われる経験則は、利用可能な GPU の数の 4 倍に設定することです。これより多くても少なくても、トレーニングが遅くなります。 num_workers を増やすと CPU メモリの消費量が増加することに注意してください。

03. バッチサイズを最大に設定する

バッチ サイズを最大化するという考えは議論の余地があります。一般的に、バッチ サイズを GPU メモリが許す限り大きく設定すると、トレーニングが速くなります。ただし、学習率などの他のハイパーパラメータも調整する必要があります。経験則としては、バッチ サイズが 2 倍になると学習率も 2 倍になるはずです。

OpenAI の論文「大規模バッチトレーニングの経験的モデル」では、さまざまなバッチ サイズが収束するのに必要なステップ数について、優れたデモンストレーションが提供されています。論文「適切なバッチ サイズを使用して 4 倍のスピードアップとより優れた一般化を実現する方法」の中で、著者の Daniel Huynh は、さまざまなバッチ サイズ (前述の 1Cycle 戦略も使用) を使用していくつかの実験を実行しました。最終的に、バッチ サイズを 64 から 512 に増やし、4 倍の高速化を達成しました。

ただし、大きなバッチ サイズを使用することの欠点は、小さなバッチ サイズを使用したソリューションよりも一般化の悪いソリューションが生成される可能性があることです。

04. 自動混合精度(AMP)を使用する

PyTorch 1.6 リリースには、PyTorch の自動混合精度トレーニングのネイティブ実装が含まれています。ここでのポイントは、一部の操作は、精度を失わずに、単精度 (FP32) よりも半精度 (FP16) でより高速に実行されることです。 AMP は、どの操作をどの精度で実行するかを自動的に決定します。これにより、トレーニングの速度が向上し、メモリ使用量が削減されます。

最良のシナリオでは、AMP の使用は次のようになります。

  1. 輸入トーチ 
  2. # トレーニングの開始時に1回作成します 
  3. スケーラー= torch.cuda.amp.GradScaler ()  
  4. データの場合、data_iter のラベル:  
  5. オプティマイザ.zero_grad()  
  6. # 演算を混合精度にキャストする 
  7. torch.cuda.amp.autocast() を使用する場合:  
  8. 損失=モデル(データ)  
  9. # 損失をスケールし、backward() を呼び出します 
  10. # スケールグラデーションを作成する 
  11. スケーラー.スケール(損失).後方()  
  12. # 勾配をスケール解除して呼び出します 
  13. # または optimizer.step() をスキップします 
  14. スケーラー.ステップ(オプティマイザー)  
  15. # 次の反復のスケールを更新します 
  16. スケーラー.更新()

05. 別のオプティマイザーの使用を検討する

AdamW は、fast.ai によって普及され、PyTorch で torch.optim.AdamW として実装されている、L2 正規化の代わりに重み減衰を使用する Adam のバージョンです。 AdamW は、エラーとトレーニング時間の両方で一貫して Adam を上回っているようです。

Adam と AdamW はどちらも、上記の 1Cycle 戦略に適しています。

現在、いくつかの非ローカル最適化装置も大きな注目を集めており、その中で最も有名なのは LARS と LAMB です。 NVIDA の APEX は、Adam などの一般的なオプティマイザーの融合バージョンを実装しています。 PyTorch の Adam 実装と比較すると、この実装では GPU メモリとの間の複数のパスが回避され、5% 高速化されます。

06. cudNNベンチマーク

モデル アーキテクチャが同じままで、入力サイズも同じままの場合は、torch.backends.cudnn.benchmark = True を設定します。

07. CPUとGPU間の頻繁なデータ転送に注意する

tensor.cpu() を使用してテンソルが GPU から CPU に (または tensor.cuda() を使用して CPU から GPU に) 頻繁に転送されると、コストが非常に高くなる可能性があります。 item() と .numpy() についても同様であり、これらは .detach() に置き換えることができます。

新しいテンソルを作成する場合は、キーワード引数 device=torch.device(cuda:0) を使用して GPU に割り当てることができます。

データを転送する必要がある場合は、転送後に同期ポイントがない限り、.to(non_blocking=True) を使用できます。

08. グラデーションを使用する/チェックポイントを有効にする

チェックポイントは、計算をメモリと交換することによって機能します。逆方向パスの計算グラフ全体のすべての中間アクティベーションを保存する代わりに、これらのアクティベーションが再計算されます。これをモデルのどの部分にも適用できます。

具体的には、フォワードパスでは、関数は torch.no_grad() モードで実行され、中間アクティベーションは保存されません。代わりに、フォワード パスは入力タプルと関数の引数を保存します。後方パスでは、入力と関数が取得され、前方パスが関数に対して再度評価されます。次に、中間活性化が追跡され、これらの活性化値を使用して勾配が計算されます。

したがって、これにより、特定のバッチ サイズでの実行時間がわずかに長くなる可能性がありますが、メモリ使用量は大幅に削減されます。これにより、使用されるバッチ サイズをさらに増やすことができ、GPU の使用率が向上します。

チェックポイントは torch.utils.checkpoint に実装されていますが、正しく実装するにはまだある程度の考慮と努力が必要です。 Priya Goyal は、チェックポイントの重要な側面を網羅した優れたチュートリアルを作成しました。

Priya Goyal チュートリアル アドレス:

https://github.com/prigoyal/pytorch_memonger/blob/master/tutorial/Checkpointing_for_PyTorch_models.ipynb

09. 勾配累積を使用する

バッチ サイズを増やす別の方法は、optimizer.step() を呼び出す前に、複数の .backward() パスで勾配を蓄積することです。

Hugging Face の Thomas Wolf 氏の記事「大規模なバッチでのニューラル ネットのトレーニング: 1 GPU、マルチ GPU、分散設定の実用的なヒント」では、勾配累積の使用方法を紹介しています。勾配の蓄積は次の方法で実現できます。

  1. model.zero_grad() # 勾配テンソルをリセットする 
  2. i、(入力、ラベル) を enumerate(training_set) で指定します。
  3. 予測=モデル(入力) # フォワードパス 
  4. loss = loss_function (predictions, labels) # 損失関数を計算する 
  5. loss loss = loss / acceleration_steps # 損失を正規化します(平均化されている場合)  
  6. loss.backward() # 後方パス 
  7. if (i+1) % acceleration_steps == 0: # 数ステップ後進するのを待つ 
  8. optimizer.step() # これでオプティマイザのステップを実行できます 
  9. model.zero_grad() # 勾配テンソルをリセットする 
  10. if (i+1) % evaluation_steps == 0: # 次の場合にモデルを評価します...  
  11. assess_model() # ...勾配が蓄積されない

この方法は主に GPU メモリの制限を回避するために開発されました。

10. 分散データ並列処理を使用したマルチGPUトレーニング

分散トレーニングを高速化する方法はたくさんありますが、簡単な方法は、torch.nn.DataParallel の代わりに torch.nn.DistributedDataParallel を使用することです。この方法では、各 GPU は専用の CPU コアによって駆動され、DataParallel の GIL 問題を回避します。

分散トレーニング ドキュメントのアドレス: https://pytorch.org/tutorials/beginner/dist_overview.html

11. グラデーションを0ではなくNoneに設定する

勾配は、.zero_grad() ではなく .zero_grad(set_to_none=True) で設定されます。これを行うと、メモリ アロケータは勾配を 0 に設定する代わりに、勾配を処理できるようになります。ドキュメントに記載されているように、gradient を None に設定すると、適度な速度向上が得られますが、奇跡は期待しないでください。ただし、これには欠点もあるので、詳細についてはドキュメントを参照してください。

ドキュメントアドレス: https://pytorch.org/docs/stable/optim.html

12. .tensor() の代わりに .as_tensor() を使用する

torch.tensor() は常にデータをコピーします。 numpy 配列を変換する場合は、データのコピーを回避するために torch.as_tensor() または torch.from_numpy() を使用します。

13. 必要に応じてデバッグツールを有効にする

PyTorch には、autograd.profiler、autograd.grad_check、autograd.anomaly_detection など、多くのデバッグ ツールが用意されています。デバッガーはトレーニングの速度を低下させるため、必要なときのみデバッガーを開き、必要のないときはオフにしてください。

14. グラデーションクリッピングを使用する

RNN における勾配爆発を回避する問題に関しては、勾配クリッピング (gradient = min(gradient, threshold)) によって収束を加速できることを確認する実験や理論がいくつか存在します。 HuggingFace の Transformer 実装は、グラデーション クリッピングの使用方法を示す非常に明確な例です。 AMP など、この記事で説明した他の方法もいくつか使用できます。

PyTorch では、torch.nn.utils.clip_grad_norm_ を使用してこれを実現できます。

15. BatchNormの前にバイアスをオフにする

BatchNormalization レイヤーを開始する前に、バイアス レイヤーをオフにします。 2D 畳み込み層の場合、bias キーワードを False に設定できます: torch.nn.Conv2d(...,bias=False, ...) 。

16. 検証中に勾配計算をオフにする

検証中に勾配計算を無効にするには、torch.no_grad() を使用します。

17. 入力とバッチ正規化を使用する

入力が正規化されているかどうかを再確認する必要がありますか?バッチ正規化は使用されていますか?

<<:  このツールは、テンソルの形状エラーを数秒で検出し、ML モデルのトレーニングが無駄になるのを防ぐことができます。

>>:  人工知能と現代の香水の発展

ブログ    

推薦する

マシンビジョン: 2D ビジョンと 3D ビジョンのどちらを選択するか?

マシンビジョンは、人工知能の重要な分野として、今日最も注目されているテクノロジーの 1 つとなってい...

100 日で機械学習: モデルのトレーニングが完了したら、次は何をする?

機械学習をマスターするための 100 日 | 1 日目から 62 日目までのコレクションみなさんこん...

インテリジェントプロセスオートメーションについて知っておくべきこと

インテリジェント プロセス オートメーション (IPA) とは何ですか?インテリジェント プロセス ...

AIは人間の感情を理解できるのか?

温かく思いやりのある、一緒にいてくれる「ダバイ」が欲しいと願う人は多いだろうが、ダバイのように人間の...

...

...

AIを活用してモノのインターネットを次のレベルに引き上げる方法

世界中の企業が人工知能を広く導入しています。モノのインターネットもすぐ後に続きます。実際、モノのイン...

産業オペレーションの深化が人工知能コンピューティングセンター構築の鍵

新たな科学技術革命と産業革命の到来とともに、デジタル経済は第四次産業革命の重要な礎となり、新たな組織...

小売業界におけるRPA活用事例11選

世界各国がインダストリー4.0の時代を迎える中、多くの業界団体がプロセス自動化の重要性を認識し始め、...

これでブリッジで腹筋運動ができるようになりました!中国初の3Dプリント橋が上海で公開

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

AIはインダストリー4.0の最適化段階の鍵となる

[[282511]]製造業の新たな課題製造業はインテリジェント製造に向けてアップグレードし、変革する...

マイクロソフトCEOナデラ氏:AIはルールを変えるインターネットの波のようなもの

8月18日、マイクロソフトが人工知能(AI)技術の研究開発に注力し、OpenAIに100億ドル以上を...

これらは、データ構造とアルゴリズムにおける動的プログラミングのコツです。

[[442276]]動的計画法理論の基礎動的プログラミングとは何か動的プログラミング (英語: D...

AIと宇宙技術が日常生活をどう改善するか

衛星から都市計画まで、人工知能の進歩は新たな洞察をもたらしています。 [[270081]]宇宙技術と...