Sofortantwort
SFT einfach erklärt
Training auf Instruktions-Daten nach dem Pre-Training.
- Kurz gesagt
- Trainiert Modelle auf (Instruktion, Antwort)-Paare
- Typischer Einsatz
- Chat-Modelle, Task-spezifische Assistenten, Domain-Anpassung
- Wichtig zu wissen
- Vorstufe zu RLHF/DPO für weitere Alignment
Supervised Fine-Tuning im Überblick
SFT (Supervised Fine-Tuning) trainiert ein vortrainiertes Sprachmodell darauf, Instruktionen zu befolgen. Nach dem Pre-Training kann ein Modell Text vervollständigen – nach SFT kann es Fragen beantworten und Aufgaben erledigen.
Der Unterschied:
Base Model (nach Pre-Training):
Input: "Was ist die Hauptstadt von Frankreich?"
Output: "Was ist die Hauptstadt von Deutschland? Was ist..."
↑ Vervollständigt nur, antwortet nicht
SFT Model:
Input: "Was ist die Hauptstadt von Frankreich?"
Output: "Die Hauptstadt von Frankreich ist Paris."
↑ Versteht und beantwortet die Frage
Die Training-Pipeline:
┌─────────────────┐
│ Pre-Training │ Riesige Textmengen, Next-Token-Prediction
│ (Base Model) │ → Sprachverständnis
└────────┬────────┘
↓
┌─────────────────┐
│ SFT │ (Instruktion, Antwort)-Paare
│ │ → Instruktionen befolgen
└────────┬────────┘
↓
┌─────────────────┐
│ RLHF / DPO │ Menschliche Präferenzen
│ (optional) │ → Besseres Alignment
└─────────────────┘
Technisch betrachtet
SFT-Datenformat
Chat-Format:
{
"messages": [
{"role": "system", "content": "Du bist ein hilfreicher Assistent."},
{"role": "user", "content": "Erkläre Photosynthese einfach."},
{"role": "assistant", "content": "Photosynthese ist der Prozess..."}
]
}
Instruction-Format:
{
"instruction": "Fasse den folgenden Text zusammen.",
"input": "Der lange Originaltext...",
"output": "Die Zusammenfassung..."
}
Training mit TRL
from trl import SFTTrainer
from transformers import AutoModelForCausalLM, AutoTokenizer
from datasets import load_dataset
# Modell und Tokenizer laden
model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3-8B")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3-8B")
# Dataset laden
dataset = load_dataset("your-sft-dataset")
# Trainer konfigurieren
trainer = SFTTrainer(
model=model,
train_dataset=dataset,
tokenizer=tokenizer,
max_seq_length=2048,
dataset_text_field="text", # Oder formatting_func
)
# Training starten
trainer.train()
Mit LoRA (effizienter)
from peft import LoraConfig
from trl import SFTTrainer
lora_config = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
)
trainer = SFTTrainer(
model=model,
train_dataset=dataset,
peft_config=lora_config, # LoRA aktivieren
max_seq_length=2048,
)
Datenqualität
Gute SFT-Daten:
- Klare, eindeutige Instruktionen
- Hochwertige, korrekte Antworten
- Vielfältige Tasks und Formate
- Konsistenter Stil
Schlechte SFT-Daten:
- Mehrdeutige Instruktionen
- Falsche oder oberflächliche Antworten
- Nur ein Task-Typ
- Inkonsistente Formatierung
Hyperparameter
| Parameter | Typischer Wert | Anmerkung |
|---|---|---|
| Learning Rate | 1e-5 bis 5e-5 | Niedriger als Pre-Training |
| Epochs | 1-3 | Mehr kann zu Overfitting führen |
| Batch Size | 4-32 | Je nach GPU-Speicher |
| Max Seq Length | 2048-4096 | Abhängig von Daten |
| Warmup | 3-10% | Stabileres Training |
Evaluation
# Perplexity auf Held-out Set
eval_results = trainer.evaluate()
# Manuelle Evaluation
test_prompts = [
"Erkläre Machine Learning.",
"Schreibe ein Gedicht über KI.",
"Was ist 15 * 23?",
]
for prompt in test_prompts:
response = model.generate(prompt)
print(f"Prompt: {prompt}")
print(f"Response: {response}\n")
SFT vs. RLHF
| Aspekt | SFT | RLHF |
|---|---|---|
| Daten | (Prompt, Response) | Präferenz-Rankings |
| Komplexität | Einfach | Komplex |
| Compute | Moderat | Hoch |
| Ergebnis | Instruktionen befolgen | Besser aligned |
| Wann nutzen | Immer als Basis | Für Top-Qualität |