Fortsatt förträning på domändata
Kunna anpassa en basmodell till ett domänkorpus och utvärdera.
Förkunskaper
- FFörträning i praktikenkrävs
Intuition
Fortsatt förträning (continued pre-training) är nästa-token-träning på ett domänkorpus — inte instruktionspar. Det används när modellen behöver lära sig ett språk eller en domän den sett för lite av: medicinsk terminologi, juridisk svenska, ett programmeringsspråk, ett företags interna begreppsvärld.
Skillnaden mot finjustering:
| Fortsatt förträning | Instruktionsfinjustering | |
|---|---|---|
| Data | löpande text, ingen struktur | (instruktion, svar)-par |
| Volym | 100 M–10 B tokens | 500–50 000 par |
| Lär sig | domänens språk och fakta | att svara i ett visst format |
| Följs av | instruktionsfinjustering | — |
Ordningen spelar roll: fortsatt förträning först, sedan instruktionsfinjustering. Gör man tvärtom raderar förträningen instruktionsbeteendet.
Formellt
Replay är inte valfritt. Tränar man enbart på domändata uppstår katastrofal glömska: modellen tappar allmän förmåga, instruktionsföljande och andra språk. Praxis är 1–10 % av den ursprungliga fördelningen blandad i korpuset (Ibrahim m.fl. 2024).
Inlärningstakt och schema: börja från en låg lr (t.ex. 10 % av den ursprungliga förträningens topp), med kort uppvärmning och avtagande schema. En hög lr «skakar loss» det modellen redan kan.
Hur mycket data behövs? Under ~100 M tokens är vinsten sällan mätbar och risken för glömska betydande — då är LoRA eller RAG bättre val. Över ~1 B tokens av verklig domäntext börjar det löna sig.
Utvärdering i tre sviter, alltid:
- Domänperplexitet på hållen domäntext (ska sjunka).
- Allmän hållbarhet (ska hållas).
- Nedströmsuppgiften efter instruktionsfinjustering — det är den som räknas.
Perplexitet som enda mått är vilseledande: den sjunker på domänen även när modellen blivit obrukbar för allt annat.
Kod
import random
def bygg_korpus(doman_dokument, allman_korpus, replay_andel=0.05, seed=0):
rng = random.Random(seed)
n_replay = int(len(doman_dokument) * replay_andel / (1 - replay_andel))
blandat = list(doman_dokument) + rng.sample(allman_korpus, min(n_replay, len(allman_korpus)))
rng.shuffle(blandat)
return blandat
KONFIG = dict(
lr=3e-5, # ~10 % av ursprunglig förträningstopp
warmup_steg=500,
schema="cosine",
epoker=1, # löpande text körs normalt en gång
replay_andel=0.05,
max_grad_norm=1.0,
)
def utvardera(modell_fore, modell_efter, sviter):
return {namn: {"fore": round(f(modell_fore), 3), "efter": round(f(modell_efter), 3)}
for namn, f in sviter.items()}
# {'doman_ppl': {'fore': 14.2, 'efter': 9.8}, ← vinsten
# 'allman_ppl': {'fore': 11.5, 'efter': 12.1}, ← acceptabel förlust
# 'instruktion': {'fore': 0.71, 'efter': 0.44}} ← förväntat: instruktionsfinjustera igen efteråt
Behärskning innebär
- Anpassar en basmodell till ett domänkorpus
- Balanserar domändata mot replay
- Mäter både domänvinst och bevarad allmän förmåga
Logga in för att göra övningarna och bygga upp din behärskning.
Källor
- arXiv — Simple and Scalable Strategies to Continually Pre-train Large Language Models — arXiv (öppen åtkomst; licens per artikel)
- arXiv — Don't Stop Pretraining: Adapt Language Models to Domains and Tasks — arXiv (öppen åtkomst; licens per artikel)