アルゴリズム最適化の概要 - Transofomer はビデオ メモリ不足と過剰なトレーニング時間を回避します

ビデオメモリ不足と過剰なトレーニング時間を回避するための Transofomer の方法

BERT の出現以来、nlp 分野は大規模モデルの時代に入りました。大規模モデルの効果は良いですが、結局のところ、誰もが豊富な GPU リソースを持っているわけではありません。訓練中にストレッチされることが多く、メモリの問題があります。メモリ不足、またはトレーニングに時間がかかります。したがって、この記事で解決すべき主な問題は、限られた GPU リソースの条件下で、トランスフォーマー ライブラリ上で大規模なモデルをトレーニングする方法です。

Huggingface のオープン ソース Transformers は自然言語処理 (NLP) タスクで驚くべき成功を収めていますが、内部のモデル パラメーターが多数であるため、トレーニングやデプロイメントに GPU を使用することさえ依然として非常に困難です。トレーニングや推論を行うと、メモリ不足 (OOM) や過剰なトレーニング時間に悩まされやすくなります。

ただし、ビデオ メモリの不足や長いトレーニング時間を回避する方法は数多くあります。この記事の主な貢献は、これらの方法の原理とその実装方法を紹介することであり、次の方法が含まれます。

  1. 勾配の累積
  2. 凍結
  3. 自動混合精度
  4. 8ビットオプティマイザー
  5. 勾配チェックポイント
  6. 高速トークナイザー
  7. 動的パディング
  8. 均一な動的パディング

このうち、1 ~ 5 はあらゆるネットワークのパフォーマンス最適化に使用できるニューラル ネットワークの一般的な手法であり、6 ~ 8 は nlp 分野のパフォーマンス最適化手法です。

勾配累積

勾配累積の背後にある考え方は非常に単純で、より大きなバッチをシミュレートします。場合によっては、収束を改善したりパフォーマンスを向上させるために、トレーニングに大規模なバッチを使用する必要がありますが、これには通常、より大きなビデオ メモリが必要になります。この問題に対する考えられる解決策は、より小さいバッチを使用することです。ただし、小さいバッチでトレーニングするとトレーニングと推論時間が増加する一方で、勾配降下アルゴリズムはバッチ サイズの選択に非常に敏感です。バッチが小さいと、収束が不安定になり、パフォーマンスが低下する可能性があります。したがって、最初に順伝播と逆伝播を数回実行して、勾配を蓄積することができます。十分な計算勾配が得られたら、パラメータを最適化して、小さなビデオ メモリを使用して大規模なバッチの効果をシミュレートできます。トレーニング時間は大幅に増加しません。
ここに画像の説明を挿入

氷結

フリーズは非常に効果的な方法で、計算モデルの一部の層 (埋め込み層、バートの最初の数層など) で勾配計算をキャンセルすることで、トレーニング速度を大幅に高速化し、メモリ使用量を削減できます。モデルのパフォーマンスをほとんど損なうことはありません。

深層学習におけるよく知られた事実は、ネットワークの最下層が入力データの一般的な特徴を学習するのに対し、ネットワークの最上層はターゲット タスクに固有の高レベルの特徴を学習するということです。事前トレーニングされたモデルでは、ネットワークの最下位層のパラメータは通常はあまり必要ありません。変更、これらは一般知識です。何らかの最適化アルゴリズム (SGD など) を使用する場合、学習する必要があるのは最上位層のパラメータです。 AdamW または RMSprop) を使用して最適化ステップを実行すると、ネットワークの最下層の勾配が非常に小さいため、パラメーターはほぼゼロになります。これは勾配消失とも呼ばれます。そのため、これらの計算に多くの時間と計算能力を費やす代わりに、下部には「役に立たない」勾配があり、小さな勾配でそのようなパラメーターを最適化するには、それらを直接フリーズする方が良いです。勾配の計算も最適化されません。

PyTorch は、勾配計算をオフにするための快適な API を提供します。これは、torch.Tensor のプロパティ require_grad を通じて設定できます。

自動混合精度

自動混合精度 (AMP) は、最終品質を損なうことなくメモリ消費量とトレーニング時間を削減するもう 1 つの方法であり、NVIDIA と Baidu の研究者が 2017 年の混合精度トレーニングに関する論文で提案しました。このメソッドの背後にある重要なアイデアは、より低い精度を使用してモデルの勾配とパラメーターをメモリ内に保持することです。つまり、完全精度 (float32) を使用する代わりに、半精度 (float16 など) を使用してテンソルをメモリ内に保持します。ただし、より低い精度で勾配を計算すると、一部の値が小さすぎてゼロとみなされる場合があり、これは「オーバーフロー」として知られる現象です。「オーバーフロー」を防ぐために、元の論文の著者は勾配スケーリング法を提案しています。

PyTorch はバージョン 1.6 以降、自動混合精度 (精度の低下から勾配スケーリングまで) を使用するために必要な関数を備えたパッケージ torch.cuda.amp を提供しています。自動混合精度はコンテキスト マネージャーとして実装されているため、いつでも挿入でき、トレーニングおよび推論スクリプトのどこにでも
ここに画像の説明を挿入

8ビットオプティマイザ

8 ビット オプティマイザーの考え方は、自動混合精度 (モデルのパラメーターと勾配が低精度で保存される) に似ていますが、8 ビット オプティマイザーでは、オプティマイザーの状態を低精度で保存することもできます。著者 (Meta Research) は、元の論文「8-bit Optimizers via Block-wise Quantization」で 8 ビット オプティマイザーを詳細に紹介し、8 ビット オプティマイザーがメモリ使用量を大幅に削減し、トレーニングをわずかに高速化することを示しました。さらに、著者らはさまざまなハイパーパラメータ設定の影響を研究し、さまざまな学習率、ベータおよび重み減衰パラメータに対する 8 ビット オプティマイザの影響が、パフォーマンスの低下や収束への影響を与えることなく安定していることを示しています。したがって、作者は bitsandbytes と呼ばれる 8 ビット オプティマイザー用の高レベル ライブラリを提供しています。

勾配チェックポイント

上記の方法を使用した後でも、特にモデルが十分に大きい場合、ビデオ メモリが十分でない場合があります。次に、勾配チェックポイント (勾配チェックポイント) が最も重要なトリックです。この方法は、サブリニア メモリ コストでディープ ネットをトレーニングするので初めてです。著者は、勾配チェックポイントがビデオ メモリの使用率を大幅に削減できることを示しています。に換算されます。ここで、n はモデルの層の数です。このアプローチにより、単一の GPU で大規模なモデルをトレーニングしたり、より多くのメモリを提供してバッチ サイズを増やしてより適切かつ高速なコンバージェンスを実現したりできます。勾配チェックポイントの背後にある考え方は、順伝播および逆伝播中にメモリから不要な勾配を削除しながら小さなチャンクで勾配を計算し、それによってメモリ使用量を削減することですが、このアプローチでは、逆伝播グラフ全体を再現するためにより多くの計算ステップが必要になります。空間の時間
ここに画像の説明を挿入

PyTorch フレームワークには、torch.utils.checkpoint.checkpoint と torch.utils.checkpoint.checkpoint_sequential の 2 つの関数を介した勾配チェックポイントの実装もあります。

聖火の公式ウェブサイトにある勾配チェックポイントの紹介は次のとおりです。

  • 勾配チェックポイントは、計算をメモリと交換することによって機能します。逆計算のために計算グラフ全体のすべての中間アクティベーションを保存する代わりに、チェックポイント部分は中間アクティベーションを保存せず、逆プロセス中に再計算します。モデルのどの部分にも適用できます。具体的には、フォワードパスでは、関数は torch.no_grad() として動作します。つまり、中間アクティベーションは保存されません。ただし、フォワード パスでは入力タプルと関数パラメーターが保存されます。バックプロパゲーション中に、保存された入力と関数が取得され、その後関数が再び順伝播され、中間のアクティベーションが追跡され、それらのアクティベーション値を使用して勾配が計算されます。

高速トークナイザー

HuggingFace Transformers は、基本トークナイザーと高速トークナイザーの 2 種類のトークナイザーを提供します。それらの主な違いは、Python はループが非常に遅いため、高速トークナイザーが Rust で書かれていることですが、トークナイズ時にはループが使用されます。高速トークナイザーは、トークン化時にさらなる高速化を可能にする非常にシンプルな方法です。高速トークナイザーの使用も非常に簡単です。transformers.AutoTokenizer の from_pretrained メソッドの use_fast 値を True に変更するだけです。

ここに画像の説明を挿入

動的塗りつぶし

通常、モデルはデータ入力のバッチでトレーニングされ、バッチ内の各入力は固定サイズである必要があります。つまり、データのバッチは行列で表され、データのすべてのバッチは同じサイズである必要があります。固定サイズは通常、データセット内の長さの分布、フィーチャの数、その他の要因に基づいて選択されます。NLP タスクでは、入力サイズはテキスト長または最大長と呼ばれます。ただし、テキストごとに長さが異なるため、この状況に対処するために、研究者はパディングマークと切り捨てを提案しています。最大長が入力テキストの長さより短い場合は切り捨てが使用されるため、一部のトークンが削除されます。入力テキストの長さが最大長に満たない場合、[PAD] などのパディング トークンが入力テキストの末尾に追加されますが、パディング トークンは損失計算に含めるべきではないことに注意してください。一部のタスク (マスクされた言語構築モデルや固有表現認識など)

ここに画像の説明を挿入

ただし、塗りつぶされたマーカーには重大な欠点があります。たとえば、入力テキストが選択された最大長に比べて非常に短い場合、効率は非常に低くなり、より多くの追加メモリが必要になります。たとえば、テキストの長さが 512 で、他のテキストの長さが約 10 である場合、 if max seq が 512 に設定されている場合、多くの無効な計算が発生します。追加の計算操作を防ぐために、研究者らは、入力のバッチをバッチの最大入力長まで埋めるという非常に効果的な方法を提案しました。以下の図に示すように、この方法によりトレーニング速度が 35% 向上します。もちろん、この方法の加速効果は、バッチのサイズとテキストの長さの分布に依存します。バッチが小さいほど、加速効果はより明白になり、テキストの長さの分布はより不均一になります。 、加速効果が高くなります。

ここに画像の説明を挿入

均一な動的塗りつぶし

バッチを分割するときにテキストの長さに応じてテキストを並べ替え、同じバッチ内のテキストの長さがほぼ同じになるようにするという考え方です。このアプローチは非常に効率的であり、トレーニング中または推論中に、動的パディングよりも必要な計算量が少なくなります。ただし、トレーニング中にデータをシャッフルすることが最善であるため、トレーニング中に均一な動的充填を使用することはお勧めできませんが、推論中に一度に大量のテキストを推論する必要がある場合は、そうすることを検討できます。

ここに画像の説明を挿入

均一な動的母集団の概要 メモリと時間の最適化は、最新の GPU 上でもモデル開発に必要な手順です。そのため、この記事では、トランスフォーマーなどの大規模なモデルのトレーニングを高速化し、メモリ消費を削減するための最も強力で一般的な方法を紹介します。

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_44077556/article/details/128115413