PEFTとLoRAによる効率的ファインチューニング準備 – コード解説

はじめに

近年、非常に高性能な大規模言語モデル(LLM)が登場していますが、これらのモデルを特定のタスクに合わせて調整(ファインチューニング)するには、膨大な計算リソースが必要になることがあります。そこで注目されているのが、少ない計算コストで効率的にファインチューニングを行う技術です。

この記事では、その中でも代表的な手法である PEFT (Parameter-Efficient Fine-Tuning)LoRA (Low-Rank Adaptation) を使って、モデルのファインチューニング準備を行うPythonコードを解説します。Google Colaboratory (Colab) 上で動作することを想定しており、コードの各行が何をしているのか、なぜそれが必要なのかをステップ・バイ・ステップで見ていきましょう。

このコードを理解することで、大規模モデルを効率的に扱うための重要な設定方法を知ることができます。これは、次に行う本格的なファインチューニング作業への大切な第一歩となります。

なお、下記のブログ記事の「4.PEFT (LoRA) の設定」の解説のエンジニア向けの解説内容となっています。

今回のコード

# モデルをk-bitトレーニング用に準備
model = prepare_model_for_kbit_training(model)

# LoRA設定
lora_config = LoraConfig(
    r=16,  # LoRAランク (8, 16, 32, 64 など。大きいほど表現力は上がるが計算量も増える)
    lora_alpha=32, # LoRAスケーリング係数 (rの2倍程度が一般的)
    # target_modulesの指定はモデル構造に依存します。elyza/Llama-3-ELYZA-JP-8B の構造を確認し、
    # 一般的なLlama系の設定を試します。['q_proj', 'k_proj', 'v_proj', 'o_proj'] だけでなく、
    # フィードフォワード層 ['gate_proj', 'up_proj', 'down_proj'] も対象に含めると効果的な場合があります。
    target_modules=[
        "q_proj",
        "k_proj",
        "v_proj",
        "o_proj",
        "gate_proj",
        "up_proj",
        "down_proj",
        # "lm_head", # 分類タスクなどでは含めることもあるが、生成では通常含めない
    ],
    lora_dropout=0.05, # LoRA層のドロップアウト率
    bias="none", # バイアス項は学習しない
    task_type="CAUSAL_LM" # タスクタイプを指定
)

# PEFTモデルの作成
model = get_peft_model(model, lora_config)

print("PEFT (LoRA) 設定完了。")
model.print_trainable_parameters() # 学習対象のパラメータ数を確認

コード解説

それでは、実際のコードを見ていきましょう。このコードは、既存の言語モデルに対してLoRAの設定を行い、学習対象のパラメータを絞り込む準備をします。

1. モデルのk-bitトレーニング準備

# Python
# モデルをk-bitトレーニング用に準備
model = prepare_model_for_kbit_training(model)

  • 何をしているか まず、prepare_model_for_kbit_training という関数を使って、モデルを「k-bitトレーニング」に適した状態に変換しています。これは、モデルが使用するメモリ量を削減するための準備作業です。特に大規模なモデルを扱う際、メモリ効率を高めることは非常に重要になります。
  • ポイント k-bitトレーニングや量子化といった技術は、モデルのパラメータをより少ないビット数で表現することで、メモリ使用量や計算負荷を軽減する手法です。この一行により、後の処理がより少ないリソースで実行できるようになります。詳細な仕組みは複雑ですが、ここでは「モデルを軽量化するための準備」と理解しておきましょう。

2. LoRA設定の定義 (LoraConfig)

# Python
# LoRA設定
lora_config = LoraConfig(
    r=16,  # LoRAランク (8, 16, 32, 64 など。大きいほど表現力は上がるが計算量も増える)
    lora_alpha=32, # LoRAスケーリング係数 (rの2倍程度が一般的)
    # target_modulesの指定はモデル構造に依存します。elyza/Llama-3-ELYZA-JP-8B の構造を確認し、
    # 一般的なLlama系の設定を試します。['q_proj', 'k_proj', 'v_proj', 'o_proj'] だけでなく、
    # フィードフォワード層 ['gate_proj', 'up_proj', 'down_proj'] も対象に含めると効果的な場合があります。
    target_modules=[
        "q_proj",
        "k_proj",
        "v_proj",
        "o_proj",
        "gate_proj",
        "up_proj",
        "down_proj",
        # "lm_head", # 分類タスクなどでは含めることもあるが、生成では通常含めない
    ],
    lora_dropout=0.05, # LoRA層のドロップアウト率
    bias="none", # バイアス項は学習しない
    task_type="CAUSAL_LM" # タスクタイプを指定 (因果言語モデリング = テキスト生成)
)

  • 何をしているか ここでは、LoRAの設定内容を LoraConfig というクラスを使って定義しています。LoRAは、元のモデルの大部分のパラメータを固定(凍結)したまま、小さな「アダプター」と呼ばれる追加層だけを学習する手法です。この設定で、そのアダプターの特性や、モデルのどの部分に適用するかなどを指定します。
  • ポイント解説
    • r (ランク) LoRAアダプターの「大きさ」を決める重要なパラメータです。値が大きいほど表現力は高まりますが、学習するパラメータ数が増え、計算負荷も上がります。一般的に8, 16, 32, 64などが使われます。
    • lora_alpha LoRAアダプターの出力をどれだけ重視するかを決めるスケーリング係数です。r の2倍程度の値がよく使われます。rlora_alpha のバランスが性能に影響します。
    • target_modules モデル内のどの層(モジュール)にLoRAアダプターを適用するかを指定するリストです。これはモデルの構造によって異なります。コメントにあるように、q_proj, k_proj, v_proj, o_proj (アテンション層に関連) や gate_proj, up_proj, down_proj (フィードフォワード層に関連) などがよく対象とされます。どの層を対象にするかで、ファインチューニングの効果が変わることがあります。
    • lora_dropout 学習中にLoRA層の一部をランダムに無効化する割合です。これにより、モデルが学習データに過剰に適合してしまう「過学習」を防ぐ効果が期待できます。
    • bias LoRAアダプター内のバイアス項を学習するかどうかを指定します。"none" は学習しない設定で、一般的によく使われます。
    • task_type ファインチューニングを行うタスクの種類を指定します。"CAUSAL_LM" は、テキスト生成タスク(前の単語に基づいて次の単語を予測するタスク)を意味します。

3. PEFTモデルの作成

# Python
# PEFTモデルの作成
model = get_peft_model(model, lora_config)

  • 何をしているか get_peft_model 関数を使い、元のモデル (model) と先ほど定義したLoRA設定 (lora_config) を組み合わせて、実際にPEFTモデルを作成しています。この時点で、元のモデルにLoRAアダプターが取り付けられ、学習対象がアダプター部分に限定された状態になります。
  • ポイント この処理によって、元の巨大なモデル全体を再学習する代わりに、追加されたごく一部のパラメータ(LoRAアダプター)だけを学習すればよくなります。これにより、計算資源(GPUメモリや時間)を大幅に節約しながら、モデルを特定のタスクに適応させることが可能になります。

4. 学習対象パラメータの確認

# Python
print("PEFT (LoRA) 設定完了。")
model.print_trainable_parameters() # 学習対象のパラメータ数を確認

  • 何をしているか 最後に、print_trainable_parameters() メソッドを呼び出して、現在のモデルで学習対象となっているパラメータの数と、それがモデル全体のパラメータ数に対してどれくらいの割合なのかを表示しています。
  • ポイント PEFTとLoRAを適用した結果、学習対象のパラメータ数が元のモデルに比べて劇的に削減されていることを確認できます。通常、この割合は数%以下、場合によっては1%未満になります。これにより、ファインチューニングがどれだけ効率化されたかを具体的に知ることができます。

まとめ

今回は、大規模言語モデルの効率的なファインチューニング準備として、PEFTとLoRAの設定を行うPythonコードを解説しました。

  • prepare_model_for_kbit_training モデルを軽量化し、メモリ効率を高める準備。
  • LoraConfig LoRAアダプターの特性 (r, lora_alpha) や適用箇所 (target_modules) などを細かく定義。
  • get_peft_model 定義した設定に基づき、元のモデルにLoRAアダプターを適用。
  • print_trainable_parameters 学習対象パラメータが大幅に削減されたことを確認。

この一連の設定により、膨大な計算コストをかけずに、大規模モデルの知識を活用しつつ、特定の目的に合わせた調整(ファインチューニング)を行う準備が整いました。ここで設定したモデルを使って、次のステップでは実際にデータを用いた学習プロセスに進むことになります。今回の内容は、効率的なモデルカスタマイズの基礎となる重要な知識です。

※この記事の作成には、一部生成AI(Google Geminiなど)を利用しています。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール