02 - トランスフォーマーの微調整: LoRA、QLoRA、アダプター
Llama 3、Mistral、GPT-4、Claude などの事前トレーニング済みの Transformer モデルが所有 言語と推論に関する優れた知識があるが、それらが準備ができていることはほとんどありません 特定のタスクに使用します。それらを分類という私たちの領域に適応させるため ビジネスメールの作成、独自のフレームワークでのコードの生成、または質問への回答 医療、必要です 微調整.
問題は、これらのモデルには数十億のパラメーターがあることです。LLaMA 2 には 70 億ものパラメーターがあります。 最小バージョンでは 700 億、最大バージョンでは 700 億です。 LLaMA-7B の完全な微調整 FP32 の重みだけで約 28 GB の VRAM が必要で、さらにオプティマイザの状態にも同様の VRAM が必要です アダムの(最初と二番目の瞬間)、さらに勾配とアクティベーションのメモリ。で 実際には、1 回の微調整実行に 4 台の 80GB A100 が必要です。
このシリーズの 2 番目の記事では、 高度なディープラーニングとエッジ展開、 のテクニックを探っていきます パラメータ効率の良い微調整 (PEFT) それ これにより、リソースの一部を使用して、数十億のパラメーターを使用してモデルを適合させることができます。 フルファインチューニングの問題から始めて、LoRA、QLoRA、DoRAを詳細に分析します アダプター層。HuggingFace PEFT を使用した Python での完全な実装。
シリーズ概要
| # | アイテム | 集中 |
|---|---|---|
| 1 | トランスフォーマーの注意メカニズム | 自己注意、マルチヘッド、完全なアーキテクチャ |
| 2 | 現在位置 - LoRA、QLoRA、アダプターによる微調整 | パラメータ効率の高い微調整 |
| 3 | モデルの量子化 | INT8、INT4、GPTQ、AWQ |
| 4 | 剪定と圧縮 | パラメータの削減、蒸留 |
| 5 | 知識の蒸留 | 教師と生徒、知識の伝達 |
| 6 | オラマとLLMローカル | 局所推論、最適化 |
| 7 | ビジョントランスフォーマー | ViT、DINO、画像分類 |
| 8 | エッジ展開 | ONNX、TensorRT、モバイル デバイス |
| 9 | NAS と AutoML | ニューラル アーキテクチャの検索 |
| 10 | ベンチマークと最適化 | プロファイリング、メトリクス、チューニング |
何を学ぶか
- なぜなら、数十億のパラメータを持つモデルでは完全な微調整は持続不可能だからです。
- PEFT テクニックの完全な概要: プレフィックス チューニング、プロンプト チューニング、アダプター、LoRA
- LoRA の数学: 低ランク分解、アルファによるスケーリング、ターゲット モジュール
- QLoRA: コンシューマ GPU で微調整するために 4 ビット量子化と LoRA を組み合わせる方法
- DoRA: LoRA を改善する大きさと方向への重み分解
- アダプター層: ボトルネックアダプター、並列アダプター、アダプター融合
- HuggingFace PEFT と SFTTrainer を使用した完全な実践的な実装
- データセット準備:Alpaca形式、チャットテンプレート、会話形式
- ハイパーパラメータの調整: ランク、アルファ、学習率、バッチ サイズ
- LoRA vs QLoRA vs DoRA vs 実際のベンチマークとの完全な微調整比較
- コンシューマ GPU のハードウェア要件と制限事項
1. 完全な微調整の問題
Il 完全な微調整 更新についてです みんな パラメータ 特定のデータセットでトレーニングする場合の事前トレーニング済みモデルの。あらゆる重量から、 埋め込み層の層からアテンションヘッドの層への変更は、 バックプロパゲーション。このアプローチは、サイズの大きなモデルにうまく機能しました BERT (パラメータ 1 億 1,000 万) と同様に中程度ですが、数十億にスケールすると持続不可能になります パラメータの。
1.1 計算コスト
完全な微調整が法外な理由である理由を理解するために、メモリ要件を見てみましょう。 LLaMA 2 7Bの場合:
メモリ使用量の完全な微調整 (LLaMA 2 7B)
| 成分 | Formula | メモリ |
|---|---|---|
| モデルの重み (FP16) | 7B * 2バイト | 14GB |
| グラデーション (FP16) | 7B * 2バイト | 14GB |
| オプティマイザーの状態 (Adam FP32) | 7B * 4バイト * 2 (m、v) | 56GB |
| アクティベーション (batch_size=1) | 変数 | ~8~16GB |
| 合計 | ~92-106GB |
100 GB の VRAM を処理できるコンシューマ GPU はありません。 80GB A100でも足りない 勾配チェックポイント設定や混合精度などの技術は使用しません。 LLaMA 70B については、次のように話します。 1 TB 以上のメモリが必要です。
1.2 壊滅的な忘却
完全な微調整の 2 番目の問題は、 壊滅的な忘却 (致命的な物忘れ)。特定のデータセットのすべてのパラメータを更新すると、 モデルは事前トレーニング中に取得した知識を忘れる傾向があります。モデル 法的文書に基づいて微調整すると、Python コードを生成できなくなる可能性があります。 歴史の質問に答えるために。
これは、完全な微調整によってすべてのウェイトが無差別に変更されるために発生します。 一般的な言語知識をエンコードしたものも含まれます。実際には、モデルは 以前の知識が新しい知識で上書きされます。
1.3 複数のモデルの保存
企業が同じ基本モデルを 10 の異なるタスクに適用する必要がある場合 (電子メール分類、センチメント分析、医療 Q&A、レポート作成など)、 完全な微調整には、モデルの完全なコピーを 10 個保存する必要があります: LLaMA 7B の場合、 それは140GBのストレージです。 LoRA では、後で説明するように、各適応に必要な容量はわずか 10 ~ 50 MB です。 合計 100 ~ 500 MB。
完全な微調整は拡張できないため
| 問題 | 完全な微調整 | PEFT (LoRA) |
|---|---|---|
| LLaMA 7B 用 VRAM | ~100GB | ~16~24GB |
| 牽引可能なパラメータ | 70億 | ~4,000,000 (0.06%) |
| 適応のためのストレージ | 14GB | 10~50MB |
| 壊滅的な忘却 | 高リスク | 最小限のリスク |
| 必要なハードウェア | 4x A100 80GB | 1x RTX 3090 24GB |
2. パラメータ効率の良い微調整 (PEFT): 概要
テクニック PEFT それらは基本原則を共有しています。 すべてのモデルパラメータを更新し、事前にトレーニングされた重みをフリーズしてトレーニングします 追加パラメータの小さなサブセットのみ。これにより、 メモリ要件が軽減され、トレーニングが高速化され、基本モデルの知識が保存されます。
PEFT 技術の分類
| 技術 | どこで機能するか | 追加パラメータ | 利点 |
|---|---|---|---|
| 即時チューニング | 入力埋め込み | 入力時に事前に重み付けされたソフトトークン | 非常にシンプルでパラメータが少ない |
| プレフィックスチューニング | 各注目層 | 牽引可能な K、V プレフィックス | プロンプトチューニングよりも表現力豊か |
| アダプター層 | トランスフォーマーの層の間 | ボトルネックモジュールが挿入されました | 柔軟なモジュール式 |
| LoRA | 既存の重み行列 | 低ランク行列 B および A | 推論時のオーバーヘッドゼロ |
| QLoRA | LoRA + 量子化のような | 4 ビット モデルの LoRA | コンシューマー向けGPUの微調整 |
| ドラ | LoRA+分解みたいな | 大きさ + 方向 | LoRAよりも優れた品質 |
2.1 迅速なチューニング
Il プロンプトチューニング (Lester et al., 2021) は、次のセットを追加します。 ソフトトークン 入力開始時に牽引可能。これらのトークンは実際の語彙に対応するものではありません。 ただし、これらはモデルがトレーニング中に学習する連続ベクトルです。基本モデルはそのまま 完全に凍結: ソフト トークンの埋め込みのみがトレーニングされます。
Input originale: [Classify this email: "Meeting at 3pm"]
Con prompt tuning: [T1][T2][T3]...[T20] [Classify this email: "Meeting at 3pm"]
^^^^^^^^^^^^^^^^^
20 soft tokens trainabili
(20 * d_model parametri = 20 * 4096 = 81.920 parametri)
Il modello base (7B parametri) e CONGELATO.
Solo 81.920 parametri vengono aggiornati.
迅速なチューニングは、非常に大規模なモデル (パラメータが 10B を超える) では驚くほどうまく機能します。 ただし、モデルが小さいと品質が低下します。 T5-XXL(11B)により素早いチューニングを実現 SuperGLUE での完全な微調整とほぼ同じパフォーマンス。
2.2 プレフィックスチューニング
Il プレフィックスチューニング (Li & Liang、2021) は、プロンプト チューニングのアイデアを拡張しています。 入力にのみソフト トークンを追加するのではなく、トレーニング可能なプレフィックスを入力に追加します。 のキー (K) と値 (V) 各層 注目の。これによりモデルが得られます 単純なプロンプトチューニングよりも表現力が豊かです。
Prompt Tuning:
Layer 1 Attention: Q=[input], K=[input], V=[input]
Layer 2 Attention: Q=[input], K=[input], V=[input]
Solo soft tokens preposti all'input iniziale.
Prefix Tuning:
Layer 1 Attention: Q=[input], K=[prefix_1 | input], V=[prefix_1 | input]
Layer 2 Attention: Q=[input], K=[prefix_2 | input], V=[prefix_2 | input]
...
Layer L Attention: Q=[input], K=[prefix_L | input], V=[prefix_L | input]
Prefissi trainabili a OGNI layer di attention.
Parametri: L * prefix_len * 2 * d_model (2 per K e V)
Esempio: 32 layer * 20 prefix * 2 * 4096 = 5.242.880 parametri
3. LoRA: 低ランクの適応
LoRA (Hu et al., 2021) および最も使用されている代表的な PEFT 手法 大規模な言語モデルの微調整における転換点です。重要なアイデアは シンプルさの点でエレガント: 重み行列を直接更新する代わりに Transformer の更新を 2 つの低ランク行列に分解します。
3.1 直観: 固有ランク仮説
研究 (Aghajanyan et al., 2020) によると、微調整すると、 特定のタスクでは、モデルの重みの更新が 1 つに集中します。 低次元部分空間。つまり、次の行列は、 体重のアップデートには、 本質的なランク 彼よりもはるかに低い 公称サイズ。
次元 d x k の重み行列 W を考えてみましょう (たとえば、射影 LLaMA 7B アテンションのクエリの数: 4096 x 4096)。完全なアップデート 4096 x 4096 = 16,777,216 個のパラメーターの配列が必要になります。でもアップデートしたら の固有ランクは低いため、はるかに小さいランク r で近似できます。
3.2 LoRA の数学
サイズ d x k の事前トレーニングされた重み行列 W_0 が与えられると、LoRA はパラメータ化します。 2 つの低ランク行列の積として更新します。
LoRA の基本式
W = W_0 + \デルタ W = W_0 + B \cdot A
どこ:
- W_0 \in \mathbb{R}^{d \times k} および事前トレーニングされた (凍結された) 重み行列
- B \in \mathbb{R}^{d \times r} そして下向き射影行列
- A \in \mathbb{R}^{r \times k} そして上向き射影行列
- r \ll \min(d, k) そして ランク (通常は 4、8、16、32、64)
スケーリングあり: h = W_0 x + \frac{\alpha}{r} \cdot B A x
どこ \アルファ そして適応の強度を制御するスケーリング係数。
Matrice originale W_0 (congelata):
k = 4096
+------------------+
| |
d = | W_0 | 16.777.216 parametri
4096| (CONGELATA) | Non viene aggiornata
| |
+------------------+
Aggiornamento LoRA (trainabile):
r = 16 k = 4096
+-----+ +------------------+
| | | |
d = | B | x r=16 | A |
4096| | | |
| | +------------------+
+-----+
65.536 65.536
B (d x r) A (r x k)
= 4096 * 16 = 16 * 4096
= 65.536 = 65.536
Totale LoRA: 131.072 parametri (0.78% di 16.777.216)
3.3 初期化
A と B の初期化は重要です。 LoRA は次のように初期化します。
- A 均一な Kaiming 初期化 (ガウス分布)
- B すべてゼロの場合
これにより、トレーニングの開始時に LoRA の寄与が正確にゼロになることが保証されます。 (B * A = 0) したがって、モデルは事前トレーニングされたモデルの動作から開始されます。 トレーニングにより B と A が徐々に変更され、モデルが特定のタスクに適応します。
3.4 スケーリング係数アルファ
パラメータ \アルファ (アルファ) 強度を制御します LoRA適応の。実際の出力は次のとおりです。
h = W_0 x + \frac{\alpha}{r} \cdot B A x
報告書 \アルファ/r 学習率のように機能します LoRA用。実際に開催されることも多いのですが、 \アルファ = 2r (例えば \アルファ = 32 con r = 16)、スケーリング係数は 2 になります。 これにより、学習率を再調整することなくランクを変更できます。
3.5 対象モジュール
LoRA はトランスフォーマーのすべてのレイヤーに適用されるのではなく、特定のマトリックスにのみ適用されます。 重みの。ターゲットモジュールの選択は、モジュールの品質に大きく影響します。 微調整:
一般的なアーキテクチャのターゲット モジュール
| モジュール | タイプ | 寸法 (LLaMA 7B) | インパクト |
|---|---|---|---|
q_proj |
アテンションクエリ | 4096×4096 | 高 - モデルが何を「探す」かを制御します |
k_proj |
アテンションキー | 4096×4096 | 高 - トークンのインデックス付け方法を制御します |
v_proj |
アテンションバリュー | 4096×4096 | 高 - 抽出された情報を制御します |
o_proj |
アテンション出力 | 4096×4096 | 中くらい |
gate_proj |
FFNゲート | 4096×11008 | 高 - FFN 内の情報フローを制御します。 |
up_proj |
FFNアップ | 4096×11008 | 中~高 |
down_proj |
FFNダウン | 11008×4096 | 中くらい |
3.6 牽引可能なパラメータの正確な計算
LoRA を q_proj と v_proj に適用して、LLaMA 2 7B のトレーニング可能なパラメーターを計算します。 32 個のレイヤーすべてで:
LLaMA 2 7B: 32 layer, d_model = 4096
Con r = 16, target_modules = ["q_proj", "v_proj"]:
Per ogni layer:
q_proj LoRA: B (4096 x 16) + A (16 x 4096) = 65.536 + 65.536 = 131.072
v_proj LoRA: B (4096 x 16) + A (16 x 4096) = 65.536 + 65.536 = 131.072
Totale per layer: 262.144
Totale: 32 layer * 262.144 = 8.388.608 parametri (8.4M)
Rapporto: 8.4M / 6.738M (totale LLaMA 7B) = 0.12% dei parametri
Con target_modules = ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]:
Per ogni layer: 7 moduli * 131.072 (media) = ~917.504
Totale: 32 * 917.504 = ~29.4M parametri = 0.44%
3.7 推論の利点: オーバーヘッドゼロ
アダプター層に対する LoRA の主な利点は、推論がないことです。 計算上のオーバーヘッドはありません。 LoRA 行列は次のことができます。 合併した 基本モデルの重みでは次のようになります。
W_{マージ済み} = W_0 + \frac{\alpha}{r} \cdot B \cdot A
マージ後、モデルのサイズと速度はまったく同じになります 元のモデルの推論を、更新された重みを使用して行います。これは不可能です アダプター層を使用すると、永続的なパラメーターがモデルに追加されます。
4. QLoRA: 量子化された LoRA
QLoRA (Dettmers et al., 2023) と、以下を組み合わせた LoRA の拡張機能です。 LoRA 微調整によるベース モデルの 4 ビット量子化。これにより、次のことが可能になります 単一の 48 GB GPU で 650 億のパラメーターを使用してモデルを微調整します。 以前は不可能だった結果。
4.1 QLoRA の 3 つのイノベーション
QLoRA では、次の 3 つの主要なテクニックを導入しています。
QLoRA イノベーション
- 4 ビット NormalFloat (NF4): 新しい最適化された量子化データ型 正規分布した重みの場合。各重みは 16 の値 (4 ビット) のいずれかにマッピングされます。 ガウス分布の量子化誤差を最小限に抑えるために選択されます。 NF4 は、ニューラル ネットワークの重みがほぼ次のとおりであるため、INT4 および FP4 よりも優れています。 正規分布。
- 二重量子化: 量子化定数 (それぞれに 1 つ) 64 の重みのブロック) 自体が 8 ビットに量子化されます。これでお金が節約できます パラメーターごとに追加の 0.37 ビット、65B モデルの場合は約 3 GB。
- ページ化されたオプティマイザー: ページ メモリ (ユニファイド メモリ) を使用する トレーニング中や移動中のメモリのスパイクを処理するための NVIDIA GPU 必要に応じて、GPU と CPU の間の状態を自動的に最適化します。
4.2 NF4 の仕組み
NF4 量子化は、よく訓練されたニューラル ネットワークの重みが それらは、平均がゼロのほぼ正規分布に従います。 NF4 は、 16 の等確率区間の標準正規分布を作成し、 各間隔で予想される誤差を最小限に抑える最適値:
INT4 (equispaziato):
Livelli: [-8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7]
Problema: molti livelli nelle code (pochi pesi li), pochi al centro (molti pesi li)
NF4 (quantili normali):
Livelli: [-1.0, -0.6962, -0.5251, -0.3949, -0.2844, -0.1848, -0.0911, 0.0,
0.0796, 0.1609, 0.2461, 0.3379, 0.4407, 0.5626, 0.7230, 1.0]
Vantaggio: livelli densi dove ci sono più pesi (vicino a 0)
Risultato: NF4 produce errore di quantizzazione ~2x inferiore a INT4
4.3 QLoRA のメモリ使用量
メモリの比較: フル FT vs LoRA vs QLoRA (LLaMA 7B)
| 成分 | フルFT(FP16) | LoRA (FP16) | QLoRA (NF4) |
|---|---|---|---|
| モデルの重み | 14GB(FP16) | 14GB(FP16) | 3.5GB(NF4) |
| グラデーション | 14GB | ~16MB | ~16MB |
| オプティマイザーの状態 | 56GB | ~64MB | ~64MB |
| アクティベーション | ~12GB | ~12GB | ~6GB |
| 合計 | ~96GB | ~26GB | ~10GB |
QLoRAを使用すると、1台のRTX 3090(24GB)でLLaMA 7Bの微調整が可能になり、 および LLaMA 13B を単一の RTX 4090 (24GB) 上で実行し、勾配チェックポイントを有効にします。
5. DoRA: 重み分解された低ランク適応
ドラ (Liu et al., 2024) とマトリックスを分解する LoRA の進化 2 つの成分の重みの計算: 大きさ (大きさ) e 方向 (方向)。この分解は古典的なものからインスピレーションを受けています Salimans & Kingma (2016) による重量の正規化と品質のギャップを埋めることを目的としています。 LoRA と完全な微調整の間。
5.1 DoRA の背後にある直観
学習パターンの分析により、完全な学習パターンと完全な学習パターンの根本的な違いが示されています。 微調整と LoRA: 完全な微調整では、大きさと方向の両方が変更されます LoRA は重みを独立して変更する傾向がありますが、 彼の表現力を制限してしまう。
5.2 DoRA の数学
DoRA は、事前トレーニングされた重み行列を次のように分解します。
DoRA公式
W' = m \cdot \frac{W_0 + BA}{\|W_0 + BA\|_c}
どこ:
- m \in \mathbb{R}^{1 \times k} および (トレーニング可能な) 大きさベクトル。次の列ノルムで初期化されます。 W_0
- W_0+BA LoRA を介して更新された方向を表します
- \|\cdot\|_c 列ノルム。各列を単位ノルムに正規化します。
- B e A 標準 LoRA 行列です (トレーニング可能)
このように、DoRA には 2 つの独立した自由度があります。
- La 方向 B と A によって制御されます (LoRA とまったく同じように)
- La 大きさ 方向に関係なく変化するベクトル m によって制御されます。
5.3 LoRA に対する DoRA の利点
DoRA 対 LoRA のベンチマーク (常識的推論、LLaMA-7B)
| タスク | LoRA (r=32) | ドラ(r=32) | フルFT |
|---|---|---|---|
| ブールQ | 69.8 | 71.8 | 73.2 |
| ピカ | 82.1 | 83.2 | 83.9 |
| ウィノグランデ | 79.4 | 80.6 | 81.5 |
| ヘラスワッグ | 83.6 | 84.4 | 85.1 |
| 平均 | 78.7 | 80.0 | 80.9 |
DoRA は、オーバーヘッドを伴いながら、LoRA と完全な微調整の間のギャップを約 60 ~ 70% 削減します。 最小パラメータの数 (追加の m ベクトルのみ)。
6. アダプター層
Gli アダプター層 (Houlsby et al., 2019) は最初の研究者の 1 つでした。 提案されたPEFT技術。アイデアはシンプルです。小型の牽引可能なモジュールを挿入します。 (アダプタ) トランスフォーマーの既存のレイヤー間に、 オリジナルの重み。
6.1 ボトルネックアダプター
クラシックアダプターとモジュール ボトルネック 3 つのコンポーネント:
- 下方投影: サイズを d_model から d_bottleneck に削減します (例: 4096 -> 64)
- 非線形性: 通常は ReLU または GELU
- アップ投影: 元のサイズに戻します (例: 64 -> 4096)
- 残留接続: アダプターの出力が入力に追加されます
Input x (dimensione d_model = 4096)
|
+----> Down-proj: W_down (4096 x 64) --> h (dimensione 64)
| |
| Non-linearita (GELU)
| |
| Up-proj: W_up (64 x 4096) <------+
| |
+------- (+) ----+ Residual Connection
|
Output (dimensione 4096)
Parametri per adapter: (4096 * 64) + (64 * 4096) = 524.288
Con 2 adapter per layer, 32 layer: 2 * 32 * 524.288 = 33.5M parametri
6.2 比較: アダプターと LoRA
アダプターと LoRA: 主な違い
| 特性 | アダプター層 | LoRA |
|---|---|---|
| 推論時のオーバーヘッド | はい (追加レイヤー) | いいえ (ウェイトをマージします) |
| 追加の遅延 | ~5~10% 増加 | 0% |
| 構成可能性 | 高 (アダプターフュージョン) | 平均(LoRAの合計) |
| 実装の容易さ | 高い | 高い |
| ライブラリのサポート | アダプターハブ、PEFT | PEFT、アンナマケモノ、ウーパールーパー |
7. HuggingFace PEFT による実用的な実装
練習に移りましょう。このセクションでは、モデルの微調整を実装します。 LoRA および QLoRA と HuggingFace PEFT ライブラリを使用するトランスフォーマー。ミストラルを使います 7B を基本モデルとして、それを命令応答タスクに適応させます。
7.1 セットアップとインストール
# Installazione delle librerie necessarie
# pip install torch transformers peft trl datasets accelerate bitsandbytes
import torch
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig,
TrainingArguments,
)
from peft import (
LoraConfig,
get_peft_model,
prepare_model_for_kbit_training,
TaskType,
)
from trl import SFTTrainer, SFTConfig
from datasets import load_dataset
# Verifica GPU disponibile
print(f"GPU: {torch.cuda.get_device_name(0)}")
print(f"VRAM: {torch.cuda.get_device_properties(0).total_mem / 1e9:.1f} GB")
print(f"PyTorch: {torch.__version__}")
print(f"CUDA: {torch.version.cuda}")
7.2 LoRA の構成
# Configurazione LoRA per Mistral 7B
lora_config = LoraConfig(
# Rango della decomposizione low-rank
# Valori tipici: 4 (minimo), 8 (buono), 16 (ottimo), 32 (alto), 64 (massimo)
r=16,
# Alpha: fattore di scaling. Il peso effettivo e alpha/r.
# Regola pratica: alpha = 2 * r
lora_alpha=32,
# Dropout applicato ai layer LoRA durante il training
# Aiuta a prevenire l'overfitting, specialmente con dataset piccoli
lora_dropout=0.05,
# Moduli del Transformer a cui applicare LoRA
# Per Mistral/LLaMA: q_proj, k_proj, v_proj, o_proj (attention)
# gate_proj, up_proj, down_proj (FFN)
target_modules=[
"q_proj", # Query projection - impatto alto
"k_proj", # Key projection - impatto alto
"v_proj", # Value projection - impatto alto
"o_proj", # Output projection - impatto medio
"gate_proj", # FFN gate - impatto alto
"up_proj", # FFN up projection - impatto medio-alto
"down_proj", # FFN down projection - impatto medio
],
# Tipo di task
task_type=TaskType.CAUSAL_LM,
# Bias: "none" (consigliato), "all", "lora_only"
bias="none",
)
# Stampa riepilogo configurazione
print(f"Rank: {lora_config.r}")
print(f"Alpha: {lora_config.lora_alpha}")
print(f"Scaling: {lora_config.lora_alpha / lora_config.r}")
print(f"Target modules: {lora_config.target_modules}")
print(f"Dropout: {lora_config.lora_dropout}")
7.3 LoRA (FP16) による微調整
model_name = "mistralai/Mistral-7B-v0.3"
# Caricamento tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"
# Caricamento modello in FP16
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16,
device_map="auto", # Distribuzione automatica su GPU disponibili
attn_implementation="flash_attention_2", # Flash Attention per efficienza
)
# Applica LoRA al modello
model = get_peft_model(model, lora_config)
# Mostra parametri trainabili
model.print_trainable_parameters()
# Output: trainable params: 27,262,976 || all params: 7,268,633,600 || trainable%: 0.375%
# Configurazione training
training_args = SFTConfig(
output_dir="./results/mistral-lora",
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=4, # Effective batch size: 4 * 4 = 16
gradient_checkpointing=True, # Risparmia VRAM scambiando con tempo
optim="adamw_torch",
learning_rate=2e-4, # LR più alto rispetto al full FT
lr_scheduler_type="cosine",
warmup_ratio=0.03, # 3% degli step come warmup
weight_decay=0.001,
max_grad_norm=0.3,
logging_steps=10,
save_strategy="steps",
save_steps=100,
max_seq_length=2048,
fp16=True,
report_to="wandb", # Logging su Weights & Biases
seed=42,
)
7.4 QLoRA (4 ビット) による微調整
# Configurazione quantizzazione 4-bit (QLoRA)
bnb_config = BitsAndBytesConfig(
load_in_4bit=True, # Carica pesi in 4-bit
bnb_4bit_quant_type="nf4", # NormalFloat 4-bit (migliore di INT4)
bnb_4bit_compute_dtype=torch.bfloat16, # Compute in BF16 (più stabile di FP16)
bnb_4bit_use_double_quant=True, # Double quantization (risparmia ~0.4 bit/param)
)
# Caricamento modello quantizzato
model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map="auto",
attn_implementation="flash_attention_2",
)
# Prepara il modello per il training k-bit
# Questo congela i pesi quantizzati e prepara i layer per LoRA
model = prepare_model_for_kbit_training(
model,
use_gradient_checkpointing=True,
)
# Applica LoRA (stessa configurazione di prima)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# Output: trainable params: 27,262,976 || all params: 3,778,682,880 || trainable%: 0.721%
# Nota: il modello base ora occupa ~3.8GB invece di ~14GB
# Configurazione training QLoRA
training_args = SFTConfig(
output_dir="./results/mistral-qlora",
num_train_epochs=3,
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
gradient_checkpointing=True,
optim="paged_adamw_8bit", # Paged optimizer per gestire picchi di memoria
learning_rate=2e-4,
lr_scheduler_type="cosine",
warmup_ratio=0.03,
weight_decay=0.001,
max_grad_norm=0.3,
logging_steps=10,
save_strategy="steps",
save_steps=100,
max_seq_length=2048,
bf16=True, # BF16 per il compute (più stabile)
report_to="wandb",
seed=42,
)
8. データセットの準備
微調整の品質は、データセットの品質に大きく依存します。これでは セクションでは、微調整に使用される標準形式でデータを準備する方法を見てみましょう LLMの。
8.1 アルパカ形式
Alpaca 形式 (スタンフォード、2023) は、LLM 微調整で最も人気のある形式の 1 つです 指示と応答のタスクについて。各例には 3 つのフィールドがあります。
def format_alpaca(example):
"""Converte un esempio nel formato Alpaca per il fine-tuning."""
if example.get("input", ""):
# Con input aggiuntivo
text = (
f"### Instruction:\n{example['instruction']}\n\n"
f"### Input:\n{example['input']}\n\n"
f"### Response:\n{example['output']}"
)
else:
# Solo istruzione e risposta
text = (
f"### Instruction:\n{example['instruction']}\n\n"
f"### Response:\n{example['output']}"
)
return {"text": text}
# Caricamento dataset
dataset = load_dataset("tatsu-lab/alpaca", split="train")
dataset = dataset.map(format_alpaca)
# Esempio di output formattato
print(dataset[0]["text"])
# ### Instruction:
# Give three tips for staying healthy.
#
# ### Response:
# 1. Eat a balanced and nutritious diet...
# 2. Exercise regularly...
# 3. Get enough sleep...
8.2 チャットテンプレート (Mistral/ChatML)
会話モデルの場合は、チャット テンプレート形式の方が適しています。各モデル 独自の特定のテンプレートがあります。
def format_chat_template(example, tokenizer):
"""Formatta l'esempio usando il chat template del modello."""
messages = [
{"role": "system", "content": "Sei un assistente esperto e disponibile."},
{"role": "user", "content": example["instruction"]},
{"role": "assistant", "content": example["output"]},
]
# Applica il chat template del tokenizer
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=False,
)
return {"text": text}
# Formato risultante per Mistral:
# <s>[INST] Sei un assistente esperto. [/INST]
# [INST] Give three tips for staying healthy. [/INST]
# 1. Eat a balanced diet...</s>
# Per ChatML (usato da molti modelli):
# <|im_start|>system
# Sei un assistente esperto.<|im_end|>
# <|im_start|>user
# Give three tips for staying healthy.<|im_end|>
# <|im_start|>assistant
# 1. Eat a balanced diet...<|im_end|>
8.3 SFTTrainer を使用したトレーニング
from trl import SFTTrainer
# Dataset formattato
dataset = load_dataset("tatsu-lab/alpaca", split="train")
dataset = dataset.map(
lambda x: format_chat_template(x, tokenizer)
)
# Split train/eval
dataset = dataset.train_test_split(test_size=0.05, seed=42)
# Creazione trainer
trainer = SFTTrainer(
model=model,
args=training_args,
train_dataset=dataset["train"],
eval_dataset=dataset["test"],
processing_class=tokenizer,
)
# Avvio training
trainer.train()
# Salvataggio adattatore LoRA (solo ~50MB)
trainer.save_model("./results/mistral-qlora/final")
tokenizer.save_pretrained("./results/mistral-qlora/final")
9. ウェイトのマージとデプロイメント
トレーニング後、フリーズされたベース モデルと小さな LoRA アダプターが完成しました。 デプロイメントの場合、2 つを別々にしておくこともできます (相互に切り替えるのに便利です) 異なる適応)、またはそれらを単一のモデルにマージします。
9.1 LoRA 重みをベースモデルにマージする
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
# Caricamento modello base (FP16 per il merge)
base_model = AutoModelForCausalLM.from_pretrained(
"mistralai/Mistral-7B-v0.3",
torch_dtype=torch.float16,
device_map="auto",
)
# Caricamento adattatore LoRA
model = PeftModel.from_pretrained(
base_model,
"./results/mistral-qlora/final",
)
# Merge LoRA nei pesi base
# Dopo il merge: W_merged = W_0 + (alpha/r) * B * A
model = model.merge_and_unload()
# Salvataggio modello merged
model.save_pretrained("./models/mistral-7b-finetuned")
tokenizer.save_pretrained("./models/mistral-7b-finetuned")
# Upload su HuggingFace Hub
model.push_to_hub("username/mistral-7b-finetuned")
tokenizer.push_to_hub("username/mistral-7b-finetuned")
print("Modello merged e caricato su HuggingFace Hub!")
9.2 微調整モデルによる推論
from transformers import pipeline
# Pipeline di generazione
pipe = pipeline(
"text-generation",
model="./models/mistral-7b-finetuned",
torch_dtype=torch.float16,
device_map="auto",
)
# Generazione
messages = [
{"role": "system", "content": "Sei un assistente esperto di programmazione."},
{"role": "user", "content": "Spiega il pattern Repository in Python."},
]
output = pipe(
messages,
max_new_tokens=512,
temperature=0.7,
top_p=0.9,
do_sample=True,
)
print(output[0]["generated_text"][-1]["content"])
10. ハイパーパラメータの調整
良好な結果を得るには、ハイパーパラメータの選択が重要です。こちらがガイドです コミュニティの経験と公開されたベンチマークに基づいて実践します。
LoRA ハイパーパラメータ ガイド
| ハイパーパラメータ | 範囲 | アドバイス | 注意事項 |
|---|---|---|---|
| ランク(r) | 4-256 | 16-64 | 複雑なタスクの場合は増加します。分類には r=8 で十分な場合が多い |
| アルファ | 8-128 | 2 * ランク | alpha/r と効果的なスケーリング。 rを変更しても比率を一定に保つ |
| 学習率 | 1e-5 - 5e-4 | 2e-4 | フル FT (10 ~ 100x) よりも高い。損失が変動した場合は削減 |
| バッチサイズ | 1-32 | 4-8 | gradient_accumulation を使用して大規模なバッチをシミュレートする |
| エポック | 1-5 | 2-3 | 過学習に注意してください。評価損失を監視する |
| ウォームアップ率 | 0.01~0.1 | 0.03 | 安定性にとって重要です。 LRが高いほど高い |
| ドロップアウト | 0.0~0.1 | 0.05 | 大規模なデータセットの場合は 0.0、小規模なデータセットの場合は 0.1 |
| max_seq_length | 512-8192 | 2048年 | 高いほど VRAM が増加します。データセットに適応する |
微調整におけるよくある間違い
- 学習率が高すぎる: 損失は変動または発散します。解決策: LR を 2 ~ 5 分の 1 に減らすか、ウォームアップを増やします。
- ランクが低すぎる: モデルは十分に学習していません。解決策: r を 8 から 16 または 32 に増やします。
- ランクが高すぎます: 特に小さなデータセットの場合、過学習が起こります。解決策: r を減らすかドロップアウトを増やす
- いくつかの時代: フィッティングが不十分です。評価損失が低下し続けているかどうかを確認する
- 時代が多すぎる: トレーニング損失は減少しますが、評価損失は増加します (過学習)
- クリーンアップされていないデータセット: 重複、エラー、一貫性のないフォーマットにより品質が低下します
- 勾配チェックポイントのことは忘れてください。 大規模モデルでのインスタント OOM
11. ベンチマークと比較
LoRA、QLoRA、DoRA、および完全な微調整の中から選択するにはどうすればよいですか?体系的な比較は次のとおりです 公開ベンチマークとコミュニティテストに基づいています。
完全な比較: LoRA vs QLoRA vs DoRA vs Full FT
| メトリック | フルFT | LoRA | QLoRA | ドラ |
|---|---|---|---|---|
| 品質(MTベンチ) | 7.8 | 7.5 | 7.3 | 7.6 |
| VRAM(7Bモデル) | ~100GB | ~26GB | ~10GB | ~26GB |
| トレーニング速度 (相対) | 1.0倍 | 1.2倍 | 0.8倍 | 1.1倍 |
| 牽引可能なパラメータ | 100% | 0.1~0.5% | 0.1~0.5% | 0.1~0.5%+m |
| 保管適応 | 14GB | 10~50MB | 10~50MB | 10~50MB |
| 推論のオーバーヘッド | 0% | 0% (マージ) | 0% (マージ) | 0% (マージ) |
| 最小 GPU (7B) | 4x A100 | 1x A100 40GB | 1x RTX 3090 | 1x A100 40GB |
12. ハードウェア要件
ハードウェアの選択は、微調整したいモデルと PEFT テクニックによって異なります。 あなたが使っているもの。これは、コンシューマおよびプロ向け GPU のための実践的なガイドです。
微調整のための GPU 要件
| GPU | VRAM | LoRA (FP16) | QLoRA (4ビット) | 注意事項 |
|---|---|---|---|---|
| RTX3060 | 12GB | 3Bまで | 7Bまで(シーケンス512) | エントリーレベル、限定的 |
| RTX3090 | 24GB | 7Bまで | 13Bまで | QLoRA 7B に最適 |
| RTX4090 | 24GB | 7Bまで | 13Bまで | 3090 より高速、同じ VRAM |
| A100 40GB | 40GB | 13Bまで | 34Bまで | プロの基準 |
| A100 80GB | 80GB | 30Bまで | 70Bまで | 大型モデルに最適 |
| H100 80GB | 80GB | 30Bまで | 70Bまで | A100より高速、FP8サポート |
GPU コンシューマ向けのヒント
- 限られた予算 (RTX 3060 12GB): seq_length=512、batch_size=1、gradient_accumulation=16 の 7B モデル上の QLoRA
- 優れた品質/価格比 (RTX 3090/4090 24GB): seq_length=2048、batch_size=4 の 7-13B モデルの QLoRA
- クラウドコンピューティング: Google Colab Pro (月額 10 ドル) は、限られたセッションに対して A100 40GB を提供します。頻繁に使用する場合は RunPod と Lambda Labs
- 常に有効化します: gradient_checkpointing=True、ページ化されたオプティマイザー、フラッシュ アテンション 2
13. 実際の使用例
LoRA による微調整が特に効果的な具体的なユースケースをいくつか見てみましょう。
13.1 テキストの分類
分類タスク (感情分析、トピック分類、スパム検出) の場合、 多くの場合、次の理由から LoRA が推奨されます。
- このタスクにはいくつかの追加パラメーターが必要です (ランク r=4 ~ 8 で十分です)
- 分類データセットは通常小さい (1,000 ~ 50,000 例)
- 高ランクと高ランクによる過剰適合のリスク
13.2 コード生成
コード生成の微調整用 (モデルを特定の言語に適応させるなど) または会社の契約)、以下をお勧めします。
- コードの構造と可変性が高いため、ランクが高くなります (r=32-64)
- 完全なターゲット モジュール (7 つのトランス モジュールすべて)
- 高品質のデータセット: 十分に文書化されたコード、テスト付き、一貫したスタイル
- フルコンテキストの長いシーケンス (max_seq_length=4096-8192)
13.3 ドメイン固有のチャットボット
特殊なチャットボット (医療、法律、技術サポート) を作成するには:
- モデルのチャット テンプレート形式の会話データセット
- 断りの例を含める(「その質問には答えられません」)
- 平均順位 (r=16-32)
- 自動メトリクスだけでなく、ドメインの専門家による検証
13.4 概要
要約タスクを微調整するには:
- 高品質のペアを含むデータセット (ドキュメント、概要)。
- 入力用の長いシーケンス (最大 8192 トークン)
- 中~上位(r=16~32)
- ROUGEなどの指標による評価と人による評価
14. 結論と意思決定ツリー
PEFT 技術により、大規模な言語モデルの微調整が可能になりました コンシューマー向け GPU を使用している人なら誰でも。 LoRA、QLoRA、DoRA は最先端技術を表します パラメータを効率的に微調整するためのもので、それぞれに独自の長所があります。
デシジョン ツリー: いつ何を使用するか
| 状況 | おすすめのテクニック | モチベーション |
|---|---|---|
| 16 GB 未満の VRAM を搭載した GPU | QLoRA | 民生用ハードウェアの 7B+ モデルのみのオプション |
| 24~40GB VRAMを搭載したGPU | LoRA (FP16) | QLoRA よりも優れた品質、より高速なトレーニング |
| 最高の品質が求められる | ドラ | 完全な FT に近く、LoRA のオーバーヘッドは最小限に抑えられます |
| 同じモデルの複数の適応 | LoRA | 小型アダプター (~50MB)、タスク間の高速切り替え |
| 小規模モデル (< 1B パラメータ) | 完全な微調整 | 小規模なモデルの場合は、完全な FT が実現可能であり、より良い場合が多い |
| 簡単な作業(分類) | LoRA (r=4-8) | 低くても十分なランク。過学習を避ける |
| 複雑なタスク (コード生成) | LoRA/DoRA (r=32-64) | タスクの複雑さを把握するための高いランク |
| スキル構成 | アダプターの融合 | 複数の適応を構造化された方法で組み合わせる |
効率的かつ急速に進化する微調整の分野。などの新しいテクニック ガロア (勾配低ランク射影) e リロラ (ランクを上げながら反復的な LoRA トレーニング) さらなる削減を約束 フル微調整でギャップを調整します。ただし、LoRA と QLoRA は現在でも標準です ライブラリの成熟したエコシステムを備えた、事実上の LLM 微調整 (HuggingFace PEFT、Unsloth、Axolotl) と活発なコミュニティ。
シリーズの次の記事では、 モデルの量子化: GPTQ、AWQ、INT8、および品質を維持しながらモデル サイズを 75% 削減する方法 for production deployment.
リソースと参考資料
- LoRA 文書: 「LoRA: 大規模言語モデルの低ランク適応」 (Hu et al.、2021)
- QLoRA 論文: 「QLoRA: 量子化 LLM の効率的な微調整」 (Dettmers et al.、2023)
- 論文 DoRA: 「DoRA: 重み分解された低ランク適応」 (Liu et al.、2024)
- ペーパーアダプター: 「パラメータ効率の高い転移学習」(Houlsby et al.、2019)
- ハグフェイスPEFT: https://github.com/huggingface/peft
- ナマケモノを解く: https://github.com/unslothai/unsloth (LoRA 2 ~ 5 倍高速)
- TRL (トランス強化学習): https://github.com/huggingface/trl







