Llama3.1のファインチューニング!UnslothでGPUメモリ削減!

Llama3.1のファインチューニング!UnslothでGPUメモリ削減!

この記事では、Unslothを使ったLlama3.1のファインチューニング(QLoRA)を紹介します。

UnslothとQLoRAによりGPUメモリの使用量を大幅に削減して、高速にファインチューニングができるようになります。

ざっくり言うと

  • Llama3.1は、Meta社が開発した最新のLLMで、4050億のパラメータを持つ
  • Llama3.1にファインチューニングをして、未対応のタスクに適応できるようにする
  • UnslothとQLoRAによりGPUメモリを削減して、高速にファインチューニングをする

11/27開催のウェビナーをお知らせ!

目次

UnslothでLlama3.1のファインチューニング(QLoRA)

見出し画像

Unslothとは

この記事では、Unslothを使って、Llama3.1のモデルにQLoRAファインチューニングをします。

Unslothは、GPUメモリの使用量を大幅に削減して、高速にファインチューニングができるライブラリです。

Hugging FaceのSFTTrainerとも互換性があり、少ないコードでファインチューニングが実装できます。

用語の解説

QLoRA
QLoRAは、LoRAと量子化(Quantization)の2つの要素をもつファインチューニングの手法です。

LoRAは、モデルのパラメータを低ランク行列で近似することで、更新するパラメータ数を大幅に減らし計算量を削減しています。

量子化とは、モデルの精度を下げる代わりに、GPUメモリを大幅に節約する技術になります。

Llama3.1の使い方や性能・商用利用については、別記事で解説してます。

使用するデータセット

モデルの学習にはHugging Faceで公開されているデータセット「fujiki/llm-japanese-dataset_wikinews」を使用します。

ニュース記事にタイトルをつけるタスク用の日本語データセットで、4,000以上のデータが含まれています。

事前準備

見出し画像

必要なスペック・実行環境

Llama3.1のQLoRAファインチューニングでは、大容量のGPUメモリを必要とします。

この記事では、GPUメモリ80GBを搭載したNVIDIA A100 80GBのインスタンスを使用しています。

実行環境の詳細は以下のとおりです。

  • GPU:NVIDIA A100 80GB
  • GPUメモリ(VRAM):80GB
  • OS:Ubuntu22.04
  • Docker

モデルサイズとファインチューニングの種類によって、必要なGPUメモリが異なります。

この記事では、Llama3.1 70BのモデルにQLoRAのファインチューニングをするため、HuggingFaceの記事によると48GB程度のGPUメモリが必要とされます。(この記事での実測では66GB程度のGPUメモリを消費していました。)

モデルサイズフルファインチューニングLoRAQ-LoRA
8B60GB16GB6GB
70B500GB160GB48GB
405B3.25TB950GB250GB

Llama3.1のモデル利用申請

Llama3.1のモデルを使うにあたって、利用申請が必要になります。

以下の記事で利用申請の方法を紹介しています。

Dockerで環境構築

見出し画像

Dockerを使用してLlama3.1の環境構築をしていきます。

Dockerの使い方は以下の記事をご覧ください。

STEP
Dockerfileの作成

Ubuntuのコマンドラインから、Dockerfileを作成します。

mkdir llama31_unsloth
cd llama31_unsloth
nano Dockerfile

次の記述をコピーしてDockerfileに貼り付けます。

# ベースイメージ(CUDA)の指定
FROM nvidia/cuda:12.1.0-cudnn8-devel-ubuntu22.04

# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y python3-pip python3-venv git nano

# 作業ディレクトリを設定
WORKDIR /app

# アプリケーションコードをコピー
COPY . /app

# Python仮想環境の作成
RUN python3 -m venv /app/.venv

# 仮想環境をアクティベートするコマンドを.bashrcに追加
RUN echo "source /app/.venv/bin/activate" >> /root/.bashrc

# JupyterLab,HuggingFaceHub,WandBのインストール
RUN /app/.venv/bin/pip install Jupyter \
    jupyterlab \
    huggingface_hub[cli] \
    wandb

# PyTorch,Tritonのインストール
RUN /app/.venv/bin/pip install torch==2.2.0 torchvision==0.17.0 torchaudio==2.2.0 triton --index-url https://download.pytorch.org/whl/cu121

# Wheelのインストール
RUN /app/.venv/bin/pip install wheel

#Unslothをインストール 
RUN /app/.venv/bin/pip install "unsloth[cu121-ampere-torch220] @ git+https://github.com/unslothai/unsloth.git"

# コンテナの起動時にbashを実行
CMD ["/bin/bash"]

[Ctrl + S]キーで変更内容を保存し、[Ctrl + X]キーで編集モードから抜けます。

コマンドの説明

FROM nvidia/cuda:12.1.0-cudnn8-devel-ubuntu22.04

CUDA12.1のベースイメージを指定しています。

RUN apt-get update && apt-get install -y python3-pip python3-venv git nano

必要なパッケージをインストールしています。

RUN /app/.venv/bin/pip install torch==2.2.0 torchvision==0.17.0 torchaudio==2.2.0 triton –index-url https://download.pytorch.org/whl/cu121

PyTorchをインストールしています。PyTorchのバージョンはCUDA12.1に合わせています。

RUN /app/.venv/bin/pip install “unsloth[cu121-ampere-torch220] @ git+https://github.com/unslothai/unsloth.git”

unslothのバージョンは、CUDA12.1とPyTorch2.2.0に合わせています。

Unslothには、細かいバージョンの組み合わせがありますので、詳細はGithubをご参照ください。

STEP
docker-compose.ymlファイルの作成

docker-compose.ymlファイルを使ってDockerコンテナの設定をします。

docker-compose.ymlファイルを作成します。

nano docker-compose.yml

次の記述をコピーしてdocker-compose.ymlに貼り付けます。

services:
  llama31_unsloth:
    build:
      context: .
      dockerfile: Dockerfile
    image: llama31_unsloth
    runtime: nvidia
    container_name: llama31_unsloth
    ports:
      - "8888:8888"
    volumes:
      - .:/app/unsloth
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    command: >
      bash -c '/app/.venv/bin/jupyter lab --ip="*" --port=8888 --NotebookApp.token="" --NotebookApp.password="" --no-browser --allow-root'

[Ctrl + S]キーで変更内容を保存し、[Ctrl + X]キーで編集モードから抜けます。

STEP
Dockerコンテナを起動

Dockerfileからビルドしてコンテナを起動します。   

docker compose up

Dockerの起動後にブラウザの検索窓に”localhost:8888″を入力すると、Jupyter Labをブラウザで表示できます。

localhost:8888

Llama3.1ファインチューニングの実装

見出し画像

Dockerコンテナ上で起動したJupyter Labを使って、Llama3.1のファインチューニングを実装していきます。

Jupyter Labのコードセルで以下のコマンドを実行していきます。

STEP
ライブラリのインポート

必要なライブラリをインポートします。

from unsloth import FastLanguageModel, is_bfloat16_supported
from unsloth.chat_templates import get_chat_template
import torch
from datasets import load_dataset
from trl import SFTTrainer
from transformers import TrainingArguments, AutoTokenizer
from peft import AutoPeftModelForCausalLM
from huggingface_hub import login
import wandb
STEP
外部連携の設定

モデルをダウンロードするために、HuggingFaceにログインします。

token = "*************"
login(token)

token = “*************”には、HuggingFaceで発行したアクセストークンが入ります。

HuggingFaceでアクセストークンを発行する方法は以下の記事で解説しています。

学習ログの管理をするために、WandBにログインします。(WandBを使用しない場合は省略してください。)

API_KEY = "*************"
wandb.login(key=API_KEY)

API_KEY = “*************”には、Wandbで発行したAPIキーが入ります。

WandbでAPIキーを発行する方法を以下の記事で解説しています。

STEP
モデルの設定

モデルに渡すパラメータを定義します。

max_seq_length = 2048
dtype = torch.bfloat16
load_in_4bit = True

モデルとトークナイザーのダウンロードをして読み込みます。

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/Meta-Llama-3.1-70B-bnb-4bit",
    max_seq_length = max_seq_length,
    dtype = dtype,
    load_in_4bit = load_in_4bit,
)
コードの解説

max_seq_length

モデルに供給する入力テキストの最大トークン数を指定します。

torch.bfloat16

Bfloat16は、FP32と同じ数値範囲を持ちながら、GPUメモリを節約でき、計算速度も向上します。

load_in_4bit

4bit量子化の指定をしています。モデルの精度を下げて、GPUメモリの節約ができます。

FastLanguageModel.from_pretrained

モデルとトークナイザーを読み込む設定をしています。

unsloth/llama-3-70b-bnb-4bit

llama3.1 70Bの4bit量子化モデルを指定しています。

モデルの読み込み時点でGPUメモリを消費します。

STEP
データセットの設定

モデルの学習に使用するデータセットを読み込みます。

dataset = load_dataset("fujiki/llm-japanese-dataset_wikinews", split="train")

データセットを変換するチャットテンプレートを定義します。

prompt_template = """
### Instruction:
{} 

### Input:
{} 

### Output:
{}"""

ファインチューニングをする前のモデルでテキスト生成のテストをしてみます。

sample = dataset[0]
instruction = sample["instruction"]
input_text = sample["input"]
output = ""

FastLanguageModel.for_inference(model) 

inputs = tokenizer(
    [
        prompt_template.format(instruction, input_text, output)
    ], return_tensors = "pt").to("cuda")


terminators = [
    tokenizer.eos_token_id,
    tokenizer.convert_tokens_to_ids("<|eot_id|>")
]

outputs = model.generate(
    **inputs, 
    max_new_tokens = 128,
    use_cache = True,
    eos_token_id=terminators,
    temperature=0.6,
    top_p=0.9
)
decoded_outputs = tokenizer.batch_decode(outputs,skip_special_tokens=True)
print(decoded_outputs[0])

ファインチューニング前の応答結果

### Instruction: 次のニュース記事にタイトルをつけてください。

### Input: 台湾の自由時報によると、3日、陳水扁総統夫人の呉淑珍氏と馬永成元総統府副秘書長、林徳訓総統府秘書らが国務機密費の流用容疑で、台北地方検察院により起訴された。台北地検は、総統夫人を主犯、総統府秘書であった馬氏、林氏の両名が共犯と認定した。読売新聞によれば、呉氏は2002年7月から2006年3月までの間に、機密費1,480万台湾ドル(日本円で約5,300万円)を横領し、指輪の購入など私的な目的に流用した疑いが持たれている。台北地検は陳総統本人も文書を偽造するなどして関与したと認定しているが、在任中の総統であるため、起訴することができなかった。これに対して、与党の民進党は呉総統夫人の起訴について中央評議会で審議するとともに、陳総統に対して国民の前で説明するよう要求した。自由時報によれば、野党の中国国民党と親民党は48時間以内に陳総統が辞任する事を求めた。もしそれが受け入れられなければ3回目の総統罷免案を立法院で動議する方針である。また民進党と政治的主張が近い台湾団結聯盟も、今回の罷免案に賛成する意向である。台湾団結聯盟の精神的指導者である李登輝・前総統も、12月9日に予定されている台北・高雄両直轄市の市長・市議会議員選挙において民進党候補を支援しないと述べている。一方、西日本新聞によれば、陳総統は5日夜、テレビで、「私的流用はなく、横領ではない」と述べ、容疑を否定した。また、「一審で有罪判決ならば総統を辞任する」と述べた。

### Output: 台湾の自由時報によると、3日、陳水扁総統夫人の呉淑珍氏と馬永成元総統府副秘書長、林徳訓総統府秘書らが国務機密費の流用容疑で、台北地方検察院により起訴された。台北地検は、総統夫人を主犯、総統府秘書であった馬氏、林氏の両名が共犯と認定した。読売新聞によれば、呉氏は2002年7月から2006年3月

ファインチューニング前は、ニュースタイトルが生成できていないことが分かります!

データセットから「instruction(指示)」と「input(入力)」「output(出力)」を抽出して、チャットテンプレートに変換して、データセットを更新します。

EOS_TOKEN = tokenizer.eos_token
def formatting_prompts_func(examples):
    instructions = examples["instruction"]
    inputs = examples["input"]
    outputs      = examples["output"]
    texts = []
    for instruction, input_text, output in zip(instructions, inputs, outputs):
        text = prompt_template.format(instruction, input_text, output) + EOS_TOKEN
        texts.append(text)
    return { "text" : texts, }
pass

dataset = dataset.map(formatting_prompts_func, batched = True,)
print(dataset[0]["text"])
  • EOS_TOKENを指定しないとエンドレスにトークンが生成されるので、ご注意ください。
  • モデルの学習前に、データセットをチャットテンプレートに変換しておく必要があります。
チャットテンプレート変換後のデータセットの例

###Instruction:

次のニュース記事にタイトルをつけてください。 

###Input:

台湾の自由時報によると、3日、陳水扁総統夫人の呉淑珍氏と馬永成元総統府副秘書長、林徳訓総統府秘書らが国務機密費の流用容疑で、台北地方検察院により起訴された。台北地検は、総統夫人を主犯、総統府秘書であった馬氏、林氏の両名が共犯と認定した。読売新聞によれば、呉氏は2002年7月から2006年3月までの間に、機密費1,480万台湾ドル(日本円で約5,300万円)を横領し、指輪の購入など私的な目的に流用した疑いが持たれている。台北地検は陳総統本人も文書を偽造するなどして関与したと認定しているが、在任中の総統であるため、起訴することができなかった。これに対して、与党の民進党は呉総統夫人の起訴について中央評議会で審議するとともに、陳総統に対して国民の前で説明するよう要求した。自由時報によれば、野党の中国国民党と親民党は48時間以内に陳総統が辞任する事を求めた。もしそれが受け入れられなければ3回目の総統罷免案を立法院で動議する方針である。また民進党と政治的主張が近い台湾団結聯盟も、今回の罷免案に賛成する意向である。台湾団結聯盟の精神的指導者である李登輝・前総統も、12月9日に予定されている台北・高雄両直轄市の市長・市議会議員選挙において民進党候補を支援しないと述べている。一方、西日本新聞によれば、陳総統は5日夜、テレビで、「私的流用はなく、横領ではない」と述べ、容疑を否定した。また、「一審で有罪判決ならば総統を辞任する」と述べた。 

###Output:

台北地方検察院、吳淑珍総統夫人らを起訴—国務機密費の流用容疑<|end_of_text|>

STEP
LoRAパラメータの設定

LoRAのパラメータ設定をします。

model = FastLanguageModel.get_peft_model(
    model, 
    target_modules = ["q_proj", "k_proj", "v_proj", "o_proj","gate_proj", "up_proj", "down_proj",],
    r = 8,    
    lora_alpha = 16,
    lora_dropout = 0, 
    bias = "none",
    use_gradient_checkpointing = "unsloth",
    random_state = 3407,
    max_seq_length = max_seq_length,
    use_rslora = False,
    loftq_config = None,
)
コードの解説

target_modules = [“q_proj”,…

LoRAを適用する対象のトランスフォーマの層(Target modules)を指定します。

すべての線形層にLoRAを対象にすることでモデルの適応品質が向上すると言われています。

r=8

rはファインチューニングの過程で学習される低ランク行列のサイズを表します。

rを大きくするとモデルの適応品質が向上する傾向がありますが、必ずしも直線的な関係ではありません。

rが大きくなると更新されるパラメータが増えるため、メモリ使用量が増加します。

lora_alpha:16

LoRaスケーリングのAlphaパラメータは、学習した重みをスケーリングします。

多くの文献では、Alphaを調整可能なパラメータとして扱っておらず、Alphaを16に固定してます。

STEP
学習パラメータの設定

学習パラメータを設定しています。

training_arguments = TrainingArguments(
        bf16 = True,
        group_by_length=True,
        per_device_train_batch_size = 16,
        gradient_accumulation_steps = 4,
        num_train_epochs=3,
        warmup_steps = 100,
        max_steps = 50,
        learning_rate = 2e-4,
        logging_steps = 1,
        output_dir = "outputs",
        optim = "adamw_8bit",
        report_to="wandb" 
    )
コードの解説

group_by_length=True

同じ長さのシーケンスをまとめてバッチ化して、メモリを節約しています。

per_device_train_batch_size

一度に処理するバッチのサイズを指定します。GPUメモリが不足する場合は、値を減らします。

gradient_accumulation_steps

勾配累積。この値を大きくすることで、擬似的にミニバッチのサイズを大きくすることができます。

report_to=”wandb”

WandBにログを出力します。WandBを使用しない場合は、コメントアウトしてください。

STEP
SFTTrainerの設定、学習の実行

SFTTrainerを使って教師ありファインチューニング(Supervised Fine-tuning)を実行します。

trainer = SFTTrainer(
    model = model,
    train_dataset = dataset,
    dataset_text_field = "text",
    max_seq_length = max_seq_length,
    tokenizer = tokenizer,
    args = training_arguments,
)

wandb.init(project="llama31_unsloth")
trainer.train()
model.save_pretrained("llama31_unsloth/new_model")
tokenizer.save_pretrained("llama31_unsloth/new_model")
コードの解説

SFTTrainer(…

事前に設定したモデルやトークナイザー、データセット、LoRAパラメータ、学習パラメータ等をSFTTrainerに渡しています。

wandb.init(…

WandBの記録を開始します。WandBと連携しない場合はコメントアウトしてください。

STEP
メトリクスの確認

WandBに記録されたファインチューニング実行中のメトリクスを確認します。

Loss(損失)は最初の20ステップあたりから減少し、その後は緩やかに小さくなり収束しています。

loss
(出典:https://wandb.ai/)

GPUメモリは、83%(64GB)を使用しています。

GPUメモリ使用率
(出典:https://wandb.ai/)

ファインチューニングには1時間ほどかかりました!

ファインチューニング後のモデルでテキスト生成

見出し画像

ファインチューニング後のモデルでテキスト生成をしていきます。

ファインチューニング後のモデルを読み込みます。

torch.cuda.empty_cache()

load_model, load_tokenizer = FastLanguageModel.from_pretrained(
        model_name = "llama31_unsloth/new_model",
        max_seq_length = max_seq_length,
        dtype = dtype,
        load_in_4bit = load_in_4bit,
    )
FastLanguageModel.for_inference(load_model) 
コードの解説

torch.cuda.empty_cache()

テキスト生成を実行する前に、ファインチューニングで使用していたGPUメモリをリセットしています。

FastLanguageModel.from_pretrained(…

ファインチューニング後のモデルとトークナイザーを読み込んでいます。

“次のニュース記事にタイトルをつけてください。”というプロンプトを実行します。

instruction = "次のニュース記事にタイトルをつけてください。" 
input_text = """
【シリコンバレー時事】米半導体大手エヌビディアが28日発表した2024年5~7月期決算は、売上高が前年同期比2.2倍の300億ドル(約4兆3400億円)、純利益が2.7倍の165億9900万ドルだった。
【ひと目でわかる】エヌビディアの四半期業績推移
いずれも四半期ベースの過去最高を更新。生成AI(人工知能)向け半導体の需要が引き続き旺盛だった。
AIを含むデータセンター部門の売上高が2.5倍の263億ドル。売上高全体の87%を稼いだ。ゲーム部門は16%増収。
エヌビディアは、生成AIのデータ処理に最適とされ圧倒的なシェアを誇る画像処理半導体(GPU)を武器に、5四半期連続で売上高、純利益の記録を塗り替えている。増収率こそ2~4月期(3.6倍)から縮小したが、米メディアによると、売上高は市場予想を超えた。
フアン最高経営責任者(CEO)は声明で、「生成AIは全産業に革命をもたらす」と述べた。データセンターを最新鋭にしようとする動きが活発で、記録的な収益になったと説明した。
8~10月期の売上高は325億ドル前後と予想。フアン氏は電話会見で、今後投入する半導体「ブラックウェル」について「とてつもない需要がある」と語り、先行きにも強気だった。 
"""
output = ""

inputs = load_tokenizer(
    [prompt_template.format(instruction, input_text, output)], 
    return_tensors = "pt").to("cuda")

outputs = load_model.generate(
    **inputs, 
    max_new_tokens = 128,
    use_cache = True,
    temperature=0.6,
    top_p=0.9
)
decoded_outputs = load_tokenizer.batch_decode(outputs,skip_special_tokens=True)
print(decoded_outputs[0])

### Instruction:
次のニュース記事にタイトルをつけてください。

### Input:
【シリコンバレー時事】米半導体大手エヌビディアが28日発表した2024年5~7月期決算は、売上高が前年同期比2.2倍の300億ドル(約4兆3400億円)、純利益が2.7倍の165億9900万ドルだった。
【ひと目でわかる】エヌビディアの四半期業績推移
いずれも四半期ベースの過去最高を更新。生成AI(人工知能)向け半導体の需要が引き続き旺盛だった。
AIを含むデータセンター部門の売上高が2.5倍の263億ドル。売上高全体の87%を稼いだ。ゲーム部門は16%増収。
エヌビディアは、生成AIのデータ処理に最適とされ圧倒的なシェアを誇る画像処理半導体(GPU)を武器に、5四半期連続で売上高、純利益の記録を塗り替えている。増収率こそ2~4月期(3.6倍)から縮小したが、米メディアによると、売上高は市場予想を超えた。
フアン最高経営責任者(CEO)は声明で、「生成AIは全産業に革命をもたらす」と述べた。データセンターを最新鋭にしようとする動きが活発で、記録的な収益になったと説明した。
8~10月期の売上高は325億ドル前後と予想。フアン氏は電話会見で、今後投入する半導体「ブラックウェル」について「とてつもない需要がある」と語り、先行きにも強気だった。 

Output:
エヌビディア、売上高・純利益とも過去最高を更新

実際のニュースタイトルに近いタイトルが生成されました。

生成AI・LLMのコストでお困りなら

GPUのスペック不足で生成AIの開発が思うように進まないことはありませんか?

そんなときには、高性能なGPUをリーズナブルな価格で使えるGPUクラウドサービスがおすすめです!

GPUSOROBAN
GPUSOROBAN

GPUSOROBANは、生成AI・LLM向けの高速GPUを業界最安級の料金で使用することができます。

インターネット環境さえあれば、クラウド環境のGPUサーバーをすぐに利用可能です。

大規模な設備投資の必要がなく、煩雑なサーバー管理からも解放されます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
EdgeHUBロゴ

メールマガジン登録

Stable Diffusion・LLM・RAGに関する最新情報をいち早くお届けします。

無料メルマガの配信をご希望の方は、下記フォームよりご登録ください。

    EdgeHUB編集部からのお知らせ

    無料ウェビナーのお知らせ

    11/27ウェビナー

    RAG×日本語LLMの無料オンラインウェビナー第2弾!

    開催日時:
    2024年11月27日(水) 14:00~15:00

    内容:

    • 「LlamaIndex」と「Llama-3.1-Swallow」でRAG環境を構築
    • 生成AI開発の強い味方「GPUSOROBAN」の活用方法

    このウェビナーでは、オープンソース「LlamaIndex」で構築したRAGの使い方や、デモを紹介します。

    生成AIに関心のある方、AI技術をビジネスに活かしたい方は、ぜひこの貴重な機会にご参加ください!

    こんな方におすすめ!

    • 日本語LLMの利用を検討している方
    • AI開発に携わっている方
    • 最新のAI技術やトレンドに興味がある方
    • GPUスペック不足に悩んでいる方

    \簡単1分で申し込み!/

    この記事を書いた人

    EdgeHUBは、NVIDIAクラウドパートナーである株式会社ハイレゾが運営しています。「AIと共にある未来へ繋ぐ」をテーマに、画像生成AI、文章生成AI、動画生成AI、機械学習・LLM、Stable Diffusionなど、最先端の生成AI技術の使い方をわかりやすく紹介します。

    目次