【ローカルLLM】QLoRAの複雑なパラメータを(少しでも)整理する

前回の記事でも触れたとおり、QLoRAによるLlama-2のファインチューニングで試行錯誤している。

QLoRA」は、LlamaのようなローカルLLMをファインチューンする場合に現在主流となっている手法。通常のLoRAよりもGPUリソースを大幅に節約でき、コストや時間の面でメリットがあるとされる。

パラメータ設定については、Llama-2-7BでQLoRAを行う場合の公式のスクリプトがあり、大部分は以下の設定を流用すればいいはず。

CUDA_VISIBLE_DEVICES=0 python qlora.py \
    --model_name_or_path meta-llama/Llama-2-7b-hf \
    --use_auth \
    --output_dir ./output/llama-2-guanaco-7b \
    --logging_steps 10 \
    --save_strategy steps \
    --data_seed 42 \
    --save_steps 500 \
    --save_total_limit 40 \
    --evaluation_strategy steps \
    --eval_dataset_size 1024 \
    --max_eval_samples 1000 \
    --per_device_eval_batch_size 1 \
    --max_new_tokens 32 \
    --dataloader_num_workers 1 \
    --group_by_length \
    --logging_strategy steps \
    --remove_unused_columns False \
    --do_train \
    --do_eval \
    --do_mmlu_eval \
    --lora_r 64 \
    --lora_alpha 16 \
    --lora_modules all \
    --double_quant \
    --quant_type nf4 \
    --bf16 \
    --bits 4 \
    --warmup_ratio 0.03 \
    --lr_scheduler_type constant \
    --gradient_checkpointing \
    --dataset oasst1 \
    --source_max_len 16 \
    --target_max_len 512 \
    --per_device_train_batch_size 1 \
    --gradient_accumulation_steps 16 \
    --max_steps 1875 \
    --eval_steps 187 \
    --learning_rate 0.0002 \
    --adam_beta2 0.999 \
    --max_grad_norm 0.3 \
    --lora_dropout 0.1 \
    --weight_decay 0.0 \
    --seed 0 \
    --cache_dir /gscratch/zlab/llama2 

とはいえ、LoRA初心者には「分かんないパラメータ、多すぎ…」状態だったので、ひとまず整理してみた。

ハイパーパラメータの簡単な説明

※機械学習において、学習過程を制御するためのパラメータは「ハイパーパラメータ」と呼ぶらしい(「パラメータ」は一般に、学習によって決まるパラメータを指す)。

これらの中で重要と思われる項目について、qlora.pyのヘルプの和訳とともに列挙する。なお*は補足メモ。

基本的な設定

  • model_name_or_path:default="EleutherAI/pythia-12b"。HuggingFace上のモデルの名称またはパス。

  • output_dir:default='./output'。ログとチェックポイントを出力するフォルダ。

  • bf16 / fp16:使用するGPUがbfloat16をサポートしていれば、「--bf16」でトレーニングを高速化できる。*「--bf16」未対応なら「--fp16」を指定する

ステップ数に関するハイパーパラメータ

  • logging_steps:default=10。損失(Loss)を記録するステップの頻度。

  • save_steps:default=250。チェックポイントの保存を行うステップの頻度。

  • save_total_limit: default=40。最も古いチェックポイントが上書きされるまでに保存するチェックポイントの数。

  • max_steps: default=10000。最大ステップ数。*最大ステップに到達するまで学習が続く。

トレーニング効率に関するハイパーパラメータ

データセットに関するハイパーパラメータ

  • dataset: default='alpaca'。ファインチューニングに用いるデータセット。自前のデータセットを使う場合は、パスで指定する。

  • dataset_format: default=None。使用するデータセットの形式。alpaca、chip2、self-instruct、hh-rlhfなど。

  • source_max_len: default=1024。ソース・シーケンスの最大トークン(defaultの場合、1024を超えるトークンは無視される)。*「ソース」は、データセット中のインストラクション、インプットにあたる部分。ただし、ソース(インプット)には何も入れずに、インストラクションとレスポンスとまとめてターゲット(アウトプット)に突っ込む場合もある。

  • target_max_len: default=256。ターゲット・シーケンスの最大トークン(defaultの場合、256を超えるトークンは無視される)。*「ターゲット」は、データセット中のレスポンス、アウトプットにあたる部分。target_max_lenを大きくすると、その分トレーニングの際のGPUへの負荷が大きくなるので、できるだけ適切な値を設定する。

データフォーマットについて調べ始めたら長くなりそうなので、このあたりはついては次回以降の記事で詳述。

LoRAハイパーパラメータ

これらのパラメータについては、QLoRAの元論文の4章及びAppendix Aで言及されている。そもそも語彙が理解できないので、Bingによる説明を付してみた。あくまで参考までに掲載する。

  • lora_r: default=64。Lora Rディメンション。*Bingによる説明:更新行列のランクを表すパラメータです。Rが大きいほど、更新行列は元の重みに近くなりますが、メモリや計算量も増えます。Rが小さいほど、更新行列は元の重みから離れますが、メモリや計算量も減ります。Rは、訓練するタスクやドメインに応じて調整する必要があります。*QLoRA論文での言及:「…すべてのレイヤーでLoRAを使用したところ、LoRAのrは最終的なパフォーマンスとは無関係であることがわかった」

  • lora_alpha: default=16。Loraアルファ。*Bingによる説明:LoRAのスケーリングに使われるパラメータです。更新行列のノルム(大きさ)を制限することで、LoRAの過学習や不安定さを抑える効果があります。*QLoRA論文での言及:「…LoRAアルファは常に学習率に比例するので、LoRAアルファを固定して学習率を探索する」

  • lora_dropout: default=0.0。Loraドロップアウト率。*Bingによる説明:LoRAレイヤーのドロップアウト確率のことです。更新行列の一部を無効化することで、LoRAの過学習や不安定さを抑える効果があります。*QLoRA論文での言及:「…0.05のLoRAドロップアウトは、小さなモデル(7B,13B)には有効だが、大きなモデル(33B,65B)には有効ではなかった」

Guanacoのハイパーパラメータ設定例

QLoRAの元論文で登場するLlama-1ファインチューンモデル(Guanaco)で使われたハイパーパラメータ設定は以下のとおり。学習率の2e-4は0.0002、1e-4は0.0001を示す。Sequence lengthは、Target Sequence lengthのみを指すはず(OASST1データセットにSource Sequenceは不要)。

https://huggingface.co/timdettmers/guanaco-65b

この他のパラメータについては、次のように言及されている。

全てのモデルで、ベースモデルにはNormalFloat4データ型を使用し、全ての線形レイヤーのLoRAアダプタにはBFloat16を計算データ型として使用する。LoRA $r=64$、$α=16$とした。また、Adam beta2を0.999、max grad normを0.3、LoRA dropoutを13Bまでのモデルでは0.1、33Bと65Bのモデルでは0.05とした。微調整には、一定の学習率スケジュールとページングされたAdamWオプティマイザを用いる。

https://huggingface.co/timdettmers/guanaco-65b

ロス(Loss)に関する目安

実際にトレーニングを回し始めると、トレーニング・ロスの数値を眺めながら、どこで学習を止めるか判断することになる。目安となる数字は以下の通り。

LLMのトレーニングにおける学習曲線については、以下の記事に詳しい。まだちゃんと読めていない。

望ましい学習曲線の例
Underfitな学習曲線の例


関連記事

Llama-2のQLoRAを試してみるにあたっては、下記の記事が参考になった。

自前のデータセットを使ったQLoRAについては、以下の英語記事が分かりやすかった。初心者の視点でつまづく箇所が平易に書かれ、機械翻訳でも読みやすい。

学習率とエポック数など、そもそものLoRAの基本的なパラメータの関係性については、以下の記事にわかりやすい。

QLoRAに関する元論文はこちら。

論文の前半がQLoRAの考案に関するテクニカルな説明、中盤が様々なデータセットを用いたQLoRAの実践比較、後半がQLoRAの成果物であるGuanacoという言語モデルの性能評価、という感じの構成になっている。そのため、実際にQLoRAを使うにあたっては中盤の4章・5章+末尾のAppendix A, Bが参考になりそう(読んだので記事に追記)。