本記事は、ローカル環境でLoRA(主にQLoRA)を実行するための手順書です。環境構築から学習・推論・評価、よくあるトラブルとFAQまでを一通りまとめています。
目次
概要と想定読者
- 目的: 自分のPC(ローカルGPU)でLoRA学習を回し、推論まで動かす。
- 想定読者: CUDAやPyTorchをある程度触ったことがあり、LoRAの基本を理解したい個人開発者や学生。
- 成果物: 学習済みLoRAアダプタ(PEFT形式)と動作する推論コード。
ハードウェアとOS要件
- GPU: NVIDIA(例)RTX 3090/4090, A5000 など(VRAM 16GB以上推奨。QLoRAなら12GBでも工夫で可)
- CPU/RAM: 8C/32GB以上が快適(最小でも16GB)
- OS: Ubuntu 22.04 LTS 推奨(WindowsはWSL2でも可、MacはMetalで制約あり)
- ストレージ: 200GB以上の空き(モデル・データ・チェックポイント)
ドライバとCUDA、PyTorchの対応表とインストール手順
- NVIDIA Driver: 推奨は 535+(RTX40系)または環境に合わせて最新安定版。
- CUDA Toolkit: 12.x 推奨(PyTorchビルドと合わせる)。
- PyTorch: 2.3+ を推奨(pip/condaでCUDA対応ビルドを選択)。
例(Ubuntu, conda):
# NVIDIA Driver はOSの推奨手順で導入(省略)
# conda 環境作成
conda create -n lora python=3.10 -y
conda activate lora
# PyTorch (CUDA 12.1 ビルド例) ※公式サイトのコマンドジェネレータで要確認
pip install --upgrade pip
pip install torch torchvision torchaudio --index-url <https://download.pytorch.org/whl/cu121>
# 検証
python - << 'PY'
import torch
print('torch', torch.__version__)
print('cuda?', [torch.cuda.is](<http://torch.cuda.is>)_available())
print('device count', torch.cuda.device_count())
print('capability', torch.cuda.get_device_capability() if [torch.cuda.is](<http://torch.cuda.is>)_available() else None)
PY
Python環境(conda/venv)構築
- 専用の仮想環境を作り、依存解決を閉じ込める。
- 代替として
python -m venv .venv && source .venv/bin/activate
でもOK。
依存ライブラリのインストール
pip install transformers==4.42.0 accelerate==0.33.0 peft==0.12.0 trl==0.9.6 datasets==2.20.0
pip install bitsandbytes==0.43.3 sentencepiece evaluate scipy tqdm safetensors
- 注意: bitsandbytes はGPUアーキにより相性があるため、エラー時はバージョンを前後させる。
データ準備(SFT形式とバリエーション)
最小はShareGPT/Alpaca系の会話JSONL。例:
{"messages":[
{"role":"system","content":"あなたは◯◯ドメインの厳密な回答者。根拠は文章からのみ。"},
{"role":"user","content":"第3章の◯◯について説明して"},
{"role":"assistant","content":"…独自資料に基づく模範解答…"}
]}
- ポイント
- systemで方針を固定し、userで指示、assistantで模範解答。
- packing(短サンプルをまとめる)をONにして高速化・安定化。
- ドメイン語彙を寄せたい場合は、MLP層をLoRA対象に含めると効きやすい。
学習(QLoRA+FFN対象)サンプルスクリプト
# train_ffn_lora_[local.py](<http://local.py>)
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model
from trl import SFTTrainer, SFTConfig
import torch, json
MODEL_NAME = "Qwen/Qwen2.5-1.5B-Instruct" # 例。任意のOSSモデルへ変更
DATA_PATH = "train.jsonl"
tok = AutoTokenizer.from_pretrained(MODEL_NAME, use_fast=True)
if tok.pad_token is None:
tok.pad_token = tok.eos_token
# QLoRA: 4bit 量子化で省メモリ
bnb = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
)
model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
quantization_config=bnb,
torch_dtype=torch.bfloat16,
device_map="auto",
)
# LoRA 対象:まずは FFN(LLaMA系)
lora = LoraConfig(
r=8, lora_alpha=16, lora_dropout=0.05,
target_modules=["gate_proj","up_proj","down_proj"],
task_type="CAUSAL_LM",
)
model = get_peft_model(model, lora)
# JSONL ロード
samples = [json.loads(l) for l in open(DATA_PATH, "r", encoding="utf-8").read().splitlines()]
cfg = SFTConfig(
output_dir="outputs_ffn_lora",
num_train_epochs=3,
per_device_train_batch_size=2,
gradient_accumulation_steps=16,
learning_rate=1e-4,
lr_scheduler_type="cosine",
warmup_ratio=0.05,
logging_steps=10,
save_steps=200,
bf16=True,
packing=True,
max_seq_length=2048,
)
trainer = SFTTrainer(
model=model,
tokenizer=tok,
train_dataset=samples,
dataset_text_field=None,
formatting_func=None,
args=cfg,
)
trainer.train()
[trainer.save](<http://trainer.save>)_model("outputs_ffn_lora") # LoRA アダプタ保存
実行:
python3 train_ffn_lora_[local.py](<http://local.py>)
- NeoX/GPT系などで命名が異なる場合:
print(model)
でモジュール名を確認しtarget_modules
を調整。
複数GPUや分散(Accelerate/FSDP)
accelerate config # 初回のみ
accelerate launch --num_processes 2 train_ffn_lora_[local.py](<http://local.py>)
- さらに大きいモデルでは FSDP/DeepSpeed ZeRO-3 を検討。
推論(LoRAアダプタの適用)
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
import torch
base = "Qwen/Qwen2.5-1.5B-Instruct"
tok = AutoTokenizer.from_pretrained(base, use_fast=True)
model = AutoModelForCausalLM.from_pretrained(base, load_in_4bit=True, device_map="auto")
model = PeftModel.from_pretrained(model, "outputs_ffn_lora").to(torch.bfloat16)
prompt = "独自資料の◯◯について根拠を述べて回答してください。"
ids = tok(prompt, return_tensors="pt").to(model.device)
out = model.generate(**ids, max_new_tokens=300)
print(tok.decode(out[0], skip_special_tokens=True))
評価と簡易ベンチ(品質チェック)
- 目視チェック:代表プロンプト50本でBefore/After比較。
- 自動評価:
evaluate
+ルーブリック(例:指示遵守、事実整合、文体一致)をスコア化。 - 迷ったらDPO用に A/B ペアを作って好み学習。
運用Tips(再現性・ログ・チェックポイント)
- 乱数固定(seed)、依存バージョンを
requirements.txt
に固定。 accelerate config
やtorch.cuda.get_device_name()
等の環境情報をログに残す。- チェックポイントは
save_steps
を適度に。最良モデルの保存と破棄ポリシーを決める。
トラブルシューティング
- CUDA OOM:
per_device_train_batch_size
↓、gradient_accumulation_steps
↑、max_seq_length
↓、r
を8に。 - bitsandbytesエラー:バージョンを変える、
pip install --no-cache-dir bitsandbytes==0.42.0
等。 - モジュール名不一致:
print(model)
で線形層名を確認しtarget_modules
を実機に合わせる。 - 生成が崩れる:
target_modules
にlm_head
を追加、学習率を下げる、エポック数やサンプル品質を見直す。 - 収束しない:
lr=5e-5〜2e-4
をスイープ、epochs=2–4
で調整、packingをON。
FAQ
- 何GBのVRAMが必要?
-
QLoRAなら12GBでも実行可。余裕を持つなら16〜24GB。
- 学習時間の目安は?
-
1.5B〜7Bで数万トークン・数エポックなら数分〜数十分(GPUとI/Oで変動)。
- 文体も強く寄せたい。
-
FFN(三点セット gate/up/down)を対象に含める。語彙や口癖の寄りが強くなる。
- 事実性を上げたい。
-
LoRAはスタイル寄せが得意。事実はRAGを併用。
まとめ(最短フロー)
- ドライバ・CUDA・PyTorchを適合させる
- 仮想環境+依存導入
- データ(JSONL)を整える
- 学習スクリプト実行(QLoRA+packing ON)
- 推論でLoRAアダプタ適用
- 評価して調整(学習率・対象層・r など)
-
WordPress サーバーに Python API を組み込む方法(Flask / FastAPI 編)
こんにちは。aniumaでインターンをしているryuseiです。 今回はwordpressのFAQページに使用するAIチャットボットを導入する流れをまとめていき…
-
GCP × Ubuntu で Web アプリを公開するまでの完全手順
こんにちは。anuimaでインターンをさせてもらっているryuseiです。 今回は前から試してみたかったVPS導入の前段階としてGCPを触ってみたので、実装方法…
-
Local で作った WordPress テーマを Lolipop サーバーにアップロードする手順メモ
Local (Local by Flywheel) で開発した WordPress テーマを、Lolipop レンタルサーバーに scp でアップロードする方法…
-
LoRA実践解説ローカル環境で始めるQLoRA学習ガイド:環境構築から推論・評価・トラブル対処まで完全解説LoRA実践解説
本記事は、ローカル環境でLoRA(主にQLoRA)を実行するための手順書です。環境構築から学習・推論・評価、よくあるトラブルとFAQまでを一通りまとめています。…