LoRA — Low-Rank Adaptation
Kunna förklara varför LoRA fungerar (ΔW = BA), välja target modules och rank, finjustera en modell med LoRA och utvärdera med evals.
Förkunskaper
Intuition
Full finjustering av en 7B-modell uppdaterar 7 miljarder vikter och kräver optimizer-tillstånd för alla — ~100 GB. LoRA fryser modellen och lär bara en liten lågrangig uppdatering per matris: W′ = W + ΔW med ΔW = B·A, där A är r × d och B är d × r, r ≪ d (t.ex. 8–64). För d = 4096, r = 16: 131 k parametrar i stället för 16,8 M per matris.
Varför fungerar det? Finjustering ändrar modellen i få riktningar — ΔW har låg «intrinsisk rang». Hypotesen bekräftas empiriskt: LoRA når nära full finjustering på de flesta uppgifter.
Praktiskt: target modules = vilka matriser (q, k, v, o, och ofta även MLP-lagren — det senare hjälper mest när man har budget). α/r skalar uppdateringen; håll α ≈ 2r som start. Efter träning kan BA bakas in i W — noll extra inferenskostnad. QLoRA: basmodellen i 4-bit, LoRA i bf16 → 7B tränas på 8–10 GB GPU.
Mät mot basmodellen och mot full finjustering om möjligt; LoRA med för lågt r underpresterar på uppgifter som kräver ny kunskap.
Kod
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
import torch
namn = "Qwen/Qwen2.5-1.5B"
bnb = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.bfloat16)
m = AutoModelForCausalLM.from_pretrained(namn, quantization_config=bnb, device_map="auto")
m = prepare_model_for_kbit_training(m)
cfg = LoraConfig(r=16, lora_alpha=32, lora_dropout=0.05, task_type="CAUSAL_LM",
target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"])
m = get_peft_model(m, cfg)
m.print_trainable_parameters() # ~1 % av parametrarna
# …vanlig träningsloop / Trainer på instruktionsdata (loss bara på svar), lr ~2e-4, 1–3 epoker…
m.save_pretrained("adapter/") # bara A, B — några tiotal MB
# inferens: ladda bas + adapter, eller m.merge_and_unload() för att baka in
Labben lora-tiny-labb implementerar LoRA-lagret från grunden i NumPy/PyTorch och verifierar mot referens.
Härledning
Framåt: . Parametrar: mot . Initiering: , → vid start, modellen börjar exakt som basen. Gradienter: , där — samma som full finjustering, men projicerat. Minnesvinsten kommer främst från att optimizer-tillstånd (Adam: 2 × parametrar i fp32) bara behövs för . Rang-valet: effektiv rang av vid full finjustering kan mätas via SVD; empiriskt räcker för stil/format, högre för ny faktakunskap. Skalningen gör att inlärningstakten inte behöver justeras när ändras (rsLoRA föreslår ).
Behärskning innebär
- Förklarar ΔW = BA, rank och skalning α/r
- Väljer target modules och rank och motiverar
- Finjusterar med LoRA/QLoRA och utvärderar mot basmodellen och full finjustering
Logga in för att göra övningarna och bygga upp din behärskning.
Källor
- arXiv — LoRA: Low-Rank Adaptation of Large Language Models — arXiv (öppen åtkomst; licens per artikel)
- arXiv — QLoRA: Efficient Finetuning of Quantized LLMs — arXiv (öppen åtkomst; licens per artikel)
- PEFT — dokumentation (Apache-2.0) — Apache-2.0