概要
言語モデルは、数十億個の調整可能な数値(重み)を持つ非常に巨大な関数です。テキストが与えられると、次に続く可能性のあるすべてのトークンの確率を出力します。ファインチューニングはこれらの重みを変更し、特定のコンテキストが与えられた際に、お客様が求めるような回答に高い確率を割り当てるようにします。トレーニングループは、この処理を行う手順です。これは1つの巧妙な操作ではなく、1つの単純なステップを何千回も繰り返し、そのたびに重みをわずかに調整していくプロセスです。
1ステップの仕組み
1. 順伝播(フォワードパス) サンプルのバッチがモデルを通過します。各ターゲット回答のすべての位置において、モデルは次に来るトークンについて、語彙全体(多くの場合100,000トークン以上)に対する確率分布を生成します。正解の回答はすでに分かっているため、すべての位置の予測は1回のパスで並列に行われます。モデルは自身の推測ではなく、常に正しい先行トークンを参照します。この手法は教師強制(teacher forcing)と呼ばれます。
2. 損失 各ターゲットトークンに対する損失は、モデルが正解トークンに割り当てた確率の負の対数となります。バッチの損失は、すべてのターゲットトークンにおける平均値です。コンテキストトークン(システムプロンプト、以前のやり取り、ユーザーのメッセージ)は読み込まれますが、この平均の計算からは除外(マスク)されるため、ターゲットとして選択した回答のみが評価の対象となります。
loss = − (1 / N) × Σ log p(correct token | everything before it)
N = the number of target tokens in the batch
context tokens are masked: read, never scored- モデルが正解の次トークンに0.9の確率を割り当てた場合:損失 = −ln 0.9 ≈ 0.11。
- 確率が0.5の場合:損失 = −ln 0.5 ≈ 0.69。
- 確率が0.05の場合:損失 = −ln 0.05 ≈ 3.00。
- 3つのトークンの平均:(0.11 + 0.69 + 3.00) ÷ 3 ≈ 1.26。自信を持って間違えた1つのトークンがスコアを大きく左右します。
- 規模の目安として、モデルが100,000個のトークンからランダムに推測した場合のスコアは ln 100,000 ≈ 11.5 となります。ベースモデルはすでに高い推測能力を備えているため、ファインチューニングの損失はこれよりはるかに低い値から始まります。トレーニングは、お客様の回答データに基づいてその精度をさらに高めるプロセスです。
3. 逆伝播(バックワードパス) 誤差逆伝播法(バックプロパゲーション)により、トレーニング可能なすべての重みの勾配を計算します。これは、その重みをわずかに動かした場合に、損失がどの方向にどれだけ変化するかを示すものです。この計算には順伝播の約2倍の計算コストがかかり、順伝播中に保存された中間値(アクティベーション)を必要とします。そのため、サンプルが長く、バッチサイズが大きくなるほど、より多くのGPUメモリが必要になります。
4. 更新 オプティマイザは、学習率によってスケーリングされた勾配とは逆方向に各重みを変更します。最も単純な形式である通常の勾配降下法の場合、このルールは1行で表されます。
gradient = ∂loss / ∂w how the loss changes when w changes
w (new) = w − learning_rate × gradientオプティマイザ:AdamとAdamW
言語モデルのトレーニングには、通常の勾配降下法ではなく、ほぼ常にAdamまたはその派生であるAdamWが使用されます。Adamは、すべての重みに対して2つの移動平均を保持します。1つは平均勾配(バッチ間のノイズを平滑化するモメンタム)、もう1つは勾配の2乗平均(各重みのステップをスケーリングし、常に大きな勾配を持つ重みが過大なステップを踏まないようにし、更新頻度の低い重みが停滞しないようにするもの)です。その結果、勾配の元の大きさに関係なく、各重みは1ステップあたりおよそ学習率の分だけ移動します。
AdamWは、極端な値を抑制するために重みをゼロに向かって緩やかに引き寄せる荷重減衰(weight decay)の適用方法を変更したものです。勾配に混ぜるのではなく、重みから直接減算することで、Adamの重みごとのスケーリングにおいてより確実に機能します。これは、一般的なトレーニングライブラリにおけるデフォルトのオプティマイザとなっています。
m = β1 · m + (1 − β1) · g running average of gradients (momentum)
v = β2 · v + (1 − β2) · g² running average of squared gradients
w = w − lr · m̂ / (√v̂ + ε) a step scaled separately for every weight
w = w − lr · λ · w decoupled weight decay (the "W" in AdamW)
g = gradient, m̂ and v̂ = bias-corrected m and v
usual defaults: β1 = 0.9, β2 = 0.999, ε = 1e-8これらの2つの移動平均は、学習可能なすべての重みに対して32ビット精度で保存されます。つまり、重みと勾配自体に加えて、重みごとに8バイトが追加されます。これが、完全なファインチューニングに膨大なメモリを必要とする主な理由であり、小さなアダプターのみを学習するLoRAのメモリ消費が非常に少ない理由でもあります。
ステップからモデルの完成まで
- ステップが積み重なってエポックになります。 すべての学習データに対する1回のパスが1エポックです。ファインチューニングの実行は、通常1から数エポックです。
- 学習率は実行中に変化します。 通常のスケジュールでは、初期ステップでモデルを不安定にさせず、後期ステップで微調整を行えるように、一時的に学習率を上げ(ウォームアップ)、その後ゼロに向けて下げていきます。
- 検証も並行して実行されます。 定期的に、重みを更新することなく、除外されたデータ(ホールドアウトデータ)でモデルがスコアリングされます。この検証損失(バリデーションロス)により、モデルがパターンを学習しているのか、それとも単にデータを暗記しているのかが分かります。
- その結果、新しい重みが得られます。 完全に更新されたモデルか、変更されていないベースモデルの上に適用される小さなアダプターのいずれかです。
よくある間違い
- 損失を品質スコアとして解釈すること。損失はモデルがターゲットトークンをどれだけ正確に予測できるかを示すものであり、回答の質が良いかどうかを示すものではありません。回答の質は評価によって判断されます。
- 異なるベースモデル間で損失値を比較すること。各モデルは独自のトークナイザーを使用しているため、数値を同じ尺度で比較することはできません。
- トレーニングによって誤ったターゲットが修正されると期待すること。トレーニングループは、ターゲットとして指定された回答(誤りを含む)に対して忠実に損失を下げます。
- モデルがルールを学習すると想定すること。モデルは多くの小さな調整から傾向を学習するため、わずか2つの例で示された動作はほとんど学習されません。
参考文献および関連資料
外部ソースは新しいタブで開きます。
- 01Optimizing Model ParametersPyTorch Tutorials · pytorch.org約20行のコードで構成されるループ:フォワードパス、損失、バックワードパス、オプティマイザーステップ。
- 02Linear regression: Gradient descentGoogle Machine Learning Crash Course · developers.google.com最もシンプルなモデルを用いた、勾配と損失に関するインタラクティブな入門。
- 03Adam: A Method for Stochastic OptimizationKingma & Ba, 2014 · arXiv · arxiv.org更新ルールとそのデフォルト設定が記載された、Adamの原著論文。
- 04Decoupled Weight Decay RegularizationLoshchilov & Hutter, 2017 · arXiv · arxiv.orgAdamWを紹介し、なぜ荷重減衰(weight decay)を勾配から分離すべきかを解説。
- 05Cross-entropyWikipedia · en.wikipedia.org