AIモデルとプラットフォーム

Llama 3または他のオープンソースモデルをファインチューニングするための唯一のガイド

mm
Unite.AI を Google の優先ソースに追加

大規模な言語モデル(LLM)をファインチューニングするには、事前トレーニングされたモデルを特定のタスクに適応させるために、ドメイン固有のデータセットを使用してモデルを適応させる必要があります。このプロセスでは、モデルが事前トレーニング中に獲得した一般的な言語知識を活用しながら、モデルをターゲットドメインのニュアンスに合わせて調整します。このガイドでは、QLoRA(Quantized LoRA)を使用してLlama 3をファインチューニングする手順を説明します。QLoRAは、パラメーターエフィシェントな方法でメモリ使用量と計算コストを最小限に抑えることができます。

ファインチューニングの概要

ファインチューニングには、以下の手順が含まれます:

  1. 事前トレーニング済みモデルの選択:目的のアーキテクチャに合ったベースモデルを選択します。
  2. 関連データセットの収集:タスクに特化したデータセットを収集および前処理します。
  3. ファインチューニング:データセットを使用してモデルを適応させ、特定のタスクでのパフォーマンスを向上させます。
  4. 評価:質的および量的メトリックを使用してファインチューニング済みモデルのパフォーマンスを評価します。

概念とテクニック

大規模言語モデルのファインチューニング

大規模言語モデルのファインチューニング

フルファインチューニング

フルファインチューニングでは、モデルのすべてのパラメーターを更新し、モデルを新しいタスクに特化させます。この方法では、多大な計算リソースが必要であり、非常に大きなモデルでは実用的ではありません。

パラメーターエフィシェントファインチューニング(PEFT)

PEFTでは、モデルのサブセットのパラメーターのみを更新し、メモリ要件と計算コストを削減します。このテクニックにより、モデルの一般的な知識が維持され、カタストロフィックフォゲッティングが防止されます。

ローランカ適応(LoRA)と量子化ローランカ適応(QLoRA)

LoRAでは、低ランク行列のみをファインチューニングし、QLoRAではこれらの行列を量子化してメモリフットプリントをさらに削減します。

ファインチューニング方法

  1. フルファインチューニング:タスク固有のデータセットでモデルのすべてのパラメーターをトレーニングします。この方法は非常に効果的ですが、計算コストが高く、多大なメモリが必要です。
  2. パラメーターエフィシェントファインチューニング(PEFT):モデルのサブセットのパラメーターのみを更新し、メモリ要件を削減します。LoRAやQLoRAなどのテクニックがこのカテゴリに含まれます。

LoRAとは

ファインチューニング方法の比較:QLoRAはLoRAを4ビット精度量子化とページ化最適化で強化

ファインチューニング方法の比較:QLoRAはLoRAを4ビット精度量子化とページ化最適化で強化

LoRAは、事前トレーニング済みモデルのすべての重みをファインチューニングするのではなく、2つの小さな行列をファインチューニングすることで、より効率的なファインチューニング方法です。これらの行列はLoRAアダプターを構成し、事前トレーニング済みモデルにロードされて推論に使用されます。

LoRAの主な利点

  • メモリ効率:LoRAは、モデル全体ではなく小さな行列のみをファインチューニングすることでメモリフットプリントを削減します。
  • 再利用性:元のモデルは変更されず、複数のLoRAアダプターを使用して複数のタスクを処理できます。メモリ要件は低く維持されます。

量子化LoRA(QLoRA)とは

QLoRAは、LoRAをさらに進化させた方法で、LoRAアダプターの重みを低精度(例:4ビット)に量子化します。これにより、メモリ使用量とストレージ要件がさらに削減され、パフォーマンスレベルはほぼ維持されます。

QLoRAの主な利点

  • さらに高いメモリ効率:重みの量子化により、モデルのメモリとストレージ要件が大幅に削減されます。
  • パフォーマンスの維持:精度の低下にもかかわらず、QLoRAはフル精度モデルのパフォーマンスレベルを維持します。

タスク固有の適応

ファインチューニング中、モデルのパラメーターは新しいデータセットに基づいて調整され、モデルは特定のタスクに関連するコンテンツを生成および理解する能力が向上します。このプロセスでは、事前トレーニング中に獲得した一般的な言語知識が維持され、モデルはターゲットドメインのニュアンスに合わせて調整されます。

実践的なファインチューニング

フルファインチューニングvs. PEFT

  • フルファインチューニング:モデル全体をトレーニングしますが、計算コストが高く、多大なメモリが必要です。
  • PEFT(LoRAとQLoRA):パラメーターのサブセットのみをファインチューニングし、メモリ要件を削減します。カタストロフィックフォゲッティングを防ぎ、より効率的な代替手段となります。

実装手順

  1. 環境設定:必要なライブラリをインストールし、コンピューティング環境を設定します。
  2. データセットのロードと前処理:データセットをロードし、モデルに適した形式に前処理します。
  3. 事前トレーニング済みモデルのロード:ベースモデルをロードし、QLoRAの場合は量子化構成もロードします。
  4. トークナイゼーション:データセットをトークナイゼーションしてトレーニングに準備します。
  5. トレーニング:データセットを使用してモデルをファインチューニングします。
  6. 評価:モデルを特定のタスクで評価し、質的および量的メトリックを使用します。

LLMをファインチューニングするためのステップバイステップガイド

環境の設定

このチュートリアルでは、Jupyter Notebookを使用します。KaggleのようなプラットフォームやGoogle Colabは、無料のGPU使用を提供し、実験を実行するのに適しています。

1. 必要なライブラリのインストール

まず、必要なライブラリがインストールされていることを確認します。

!pip install -qqq -U bitsandbytes transformers peft accelerate datasets scipy einops evaluate trl rouge_score

2. ライブラリのインポートと環境の設定

import os
import torch
from datasets import load_dataset
from transformers import (
AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, TrainingArguments,
pipeline, HfArgumentParser
)
from trl import ORPOConfig, ORPOTrainer, setup_chat_format, SFTTrainer
from tqdm import tqdm
import gc
import pandas as pd
import numpy as np
from huggingface_hub import interpreter_login

# Weights and Biasesのログを無効にする
os.environ['WANDB_DISABLED'] = "true"
interpreter_login()

3. データセットのロード

DialogSumデータセットを使用します。

dataset_name = "neil-code/dialogsum-test"
dataset = load_dataset(dataset_name)

4. BitsAndBytes構成の作成

モデルを4ビット形式でロードするには:

compute_dtype = getattr(torch, "float16")
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type='nf4',
bnb_4bit_compute_dtype=compute_dtype,
bnb_4bit_use_double_quant=False,
)

5. 事前トレーニング済みモデルのロード

MicrosoftのPhi-2モデルを使用します。

model_name = 'microsoft/phi-2'
device_map = {"": 0}
original_model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map=device_map,
quantization_config=bnb_config,
trust_remote_code=True,
use_auth_token=True
)

6. トークナイゼーション

トークナイザーを構成します。

tokenizer = AutoTokenizer.from_pretrained(
model_name,
trust_remote_code=True,
padding_side="left",
add_eos_token=True,
add_bos_token=True,
use_fast=False
)
tokenizer.pad_token = tokenizer.eos_token

Llama 3または他のモデルをファインチューニング

Llama 3や他の最先端のオープンソースLLMをファインチューニングする場合、最適なパフォーマンスを確保するために、特定の考慮と調整が必要です。ここでは、Llama 3、GPT-3、Mistralなどのモデルをファインチューニングするための詳細なステップとインサイトを提供します。

5.1 Llama 3を使用

モデル選択

  • Hugging Faceモデルハブから正しいモデル識別子を取得します。例:Llama 3モデルはHugging Faceでmeta-llama/Meta-Llama-3-8Bとして識別されます。
  • モデルにアクセスするために必要な場合は、Hugging Faceアカウントにログインします。

トークナイゼーション

  • Llama 3に適したトークナイザーを使用し、モデルと互換性があることを確認します。

メモリと計算

  • 大きなモデルをファインチューニングするには、多大な計算リソースが必要です。環境がメモリと処理要件を処理できることを確認します。QLoRAなどのテクニックを使用してメモリフットプリントを削減します。

例:

model_name = 'meta-llama/Meta-Llama-3-8B'
device_map = {"": 0}
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
)
original_model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map=device_map,
quantization_config=bnb_config,
trust_remote_code=True,
use_auth_token=True
)

5.2 他の人気モデル(GPT-3、Mistralなど)を使用

モデル選択

  • GPT-3やMistralなどのモデルでは、Hugging Faceモデルハブまたは他のソースから正しいモデル名と識別子を使用します。

トークナイゼーション

  • トークナイザーを正しく設定し、モデルと互換性があることを確認します。

メモリと計算

  • 各モデルには異なるメモリ要件があるため、環境を適切に設定します。

GPT-3の例:

model_name = 'openai/gpt-3'
device_map = {"": 0}
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
)
original_model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map=device_map,
quantization_config=bnb_config,
trust_remote_code=True,
use_auth_token=True
)

7. ゼロショット推論でモデルをテスト

ベースモデルをサンプル入力で評価します。

from transformers import set_seed

set_seed(42)
index = 10
prompt = dataset['test'][index]['dialogue']
formatted_prompt = f"Instruct: Summarize the following conversation.\n{prompt}\nOutput:\n"

# 出力の生成
def gen(model, prompt, max_length):
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_length=max_length)
return tokenizer.batch_decode(outputs, skip_special_tokens=True)

res = gen(original_model, formatted_prompt, 100)
output = res[0].split('Output:\n')[1]

print(f'INPUT PROMPT:\n{formatted_prompt}')
print(f'MODEL GENERATION - ZERO SHOT:\n{output}')

8. データセットの前処理

ダイアログとサマリーのペアをプロンプトに変換します。

def create_prompt_formats(sample):
blurb = "Below is an instruction that describes a task. Write a response that appropriately completes the request."
instruction = "### Instruct: Summarize the below conversation."
input_context = sample['dialogue']
response = f"### Output:\n{sample['summary']}"
end = "### End"

parts = [blurb, instruction, input_context, response, end]
formatted_prompt = "\n\n".join(parts)
sample["text"] = formatted_prompt
return sample

dataset = dataset.map(create_prompt_formats)

9. モデルのQLoRAへの準備

モデルをパラメーターエフィシェントなファインチューニングに準備します。

original_model = prepare_model_for_kbit_training(original_model)

ハイパーパラメータとその影響

ハイパーパラメータは、モデルのパフォーマンスを最適化する上で重要な役割を果たします。以下は、考慮すべき重要なハイパーパラメータです。

  1. 学習率:モデルがパラメーターを更新する速度を制御します。高い学習率では収束が速くなりますが、最適な解を超えてしまう可能性があります。低い学習率では収束が遅くなりますが、より安定した収束を保証します。
  2. バッチサイズ:モデルがパラメーターを更新する前に処理するサンプルの数です。バッチサイズが大きいと安定性が向上しますが、メモリ要件も増加します。バッチサイズが小さいとトレーニングプロセスでノイズが発生する可能性があります。
  3. 勾配蓄積ステップ:大きなバッチサイズをシミュレートするために、複数のステップで勾配を蓄積します。
  4. エポック数:データセットをモデルに通す回数です。エポック数が多いとパフォーマンスが向上しますが、過剰適合を引き起こす可能性があります。
  5. 重み減算:過剰適合を防ぐために、重みの大きさにペナルティを課す正則化テクニックです。
  6. 学習率スケジューラ:トレーニング中に学習率を調整して、パフォーマンスと収束を向上させます。

トレーニング構成をカスタマイズするには、Llama 3モデルでは異なる学習率が必要になる可能性があるため、学習率、バッチサイズ、勾配蓄積ステップなどのハイパーパラメータを調整します。

トレーニング構成の例

orpo_args = ORPOConfig(
learning_rate=8e-6,
lr_scheduler_type="linear",max_length=1024,max_prompt_length=512,
beta=0.1,per_device_train_batch_size=2,per_device_eval_batch_size=2,
gradient_accumulation_steps=4,optim="paged_adamw_8bit",num_train_epochs=1,
evaluation_strategy="steps",eval_steps=0.2,logging_steps=1,warmup_steps=10,
report_to="wandb",output_dir="./results/",
)

10. モデルのトレーニング

トレーナーを設定してトレーニングを開始します。

trainer = ORPOTrainer(
model=original_model,
args=orpo_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
tokenizer=tokenizer,
)
trainer.train()
trainer.save_model("fine-tuned-llama-3")

ファインチューニング済みモデルの評価

トレーニング後、質的および量的方法を使用してモデルのパフォーマンスを評価します。

1. 人間による評価

生成されたサマリーを人間が書いたものと比較して、品質を評価します。

2. 量的評価

ROUGEなどのメトリックを使用してパフォーマンスを評価します。

from rouge_score import rouge_scorer

scorer = rouge_scorer.RougeScorer(['rouge1', 'rouge2', 'rougeL'], use_stemmer=True)
scores = scorer.score(reference_summary, generated_summary)
print(scores)

一般的な課題と解決策

1. メモリ制限

QLoRAを使用すると、メモリ問題が軽減されます。バッチサイズとモデルサイズを処理できるだけのGPUメモリが確保されていることを確認します。

2. 過剰適合

バリデーションメトリックを監視して過剰適合を防ぎます。早期停止や重み減算などのテクニックを使用します。

3. 遅いトレーニング

バッチサイズ、学習率、勾配蓄積を調整してトレーニング速度を最適化します。

4. データ品質

データセットがクリーンで適切に前処理されていることを確認します。データ品質の低さはモデルのパフォーマンスに大きな影響を与える可能性があります。

結論

LLMをQLoRAでファインチューニングすることは、特定のタスクに大きな事前トレーニング済みモデルを適応させるための効率的な方法です。このガイドに従うことで、PHI、Llama 3、または他のオープンソースモデルをファインチューニングして、特定のタスクで高パフォーマンスを達成できます。

私は過去5年間、機械学習とディープラーニングの魅力的世界に没頭してきました。私の情熱と専門知識は、AI/MLに特に焦点を当てた50以上の多様なソフトウェアエンジニアリングプロジェクトに貢献することになりました。私の継続的な好奇心は、自然言語処理という分野にも私を引き付け、さらに探求したいと思っています。