Fine-Tuning ist das Anpassen eines vortrainierten Modells an spezifische Aufgaben oder Stile. Anders als RAG (External Knowledge) oder Prompting, trainiert Fine-Tuning die Gewichte des Modells selbst.
Fine-Tuning vs. Alternativen: Wann sinnvoll?
Szenario 1: Neuer Stil / Tone
Problem: "ChatGPT schreibt zu formell, ich brauche lockerer Ton"
Option A: Prompting ("Schreib locker und lustig")
Result: Mittelmäßig, nicht konsistent
Option B: Fine-Tuning auf 500 deiner Beispiele (lockerer Ton)
Result: Hervorragend, konsistent, verlässlich
Cost: €100-300
Time: 30 Minuten
Verdict: ✅ LOHNT SICH
Szenario 2: Neues Fachgebiet (z.B. Medizin)
Problem: "Gpt-4 antwortet zu generisch bei medizinischen Fragen"
Option A: RAG mit medizinischen Artikeln
Result: Gut, aktuell, Quellen verfolgbar
Cost: ~€50 (API), Zeit: 1 Woche Setup
Verdict: ✅ BESSER als Fine-Tuning
Option B: Fine-Tuning auf medizinischen Dataset
Result: Gut, aber:
- Risiko von Halluzinationen steigt
- Legal-Compliance schwierig
- Muss bei neuen Forschungen neu trainieren
Cost: €500-2000
Time: Tage
Verdict: ❌ RAG besser für Wissen
Szenario 3: Spezifisches Ausgabeformat
Problem: "Modell muss IMMER JSON mit strukturierten Feldern ausgeben"
Option A: Structured Output / Function Calling
Result: Schnell, zuverlässig, kostenlos
Verdict: ✅ TÖDLICHE WAFFE
Option B: Fine-Tuning
Result: Besser, aber komplexer
Verdict: ❌ Overkill
Szenario 4: Sehr spezifische Domain + Kosten-Limits
Problem: "Ich hab 10.000 Beispiele von Kundensupport-Tickets,
ChatGPT kostet bei Skalierung zu viel"
Option A: Fine-Tuning auf 7B Modell (Llama 3 7B)
Result: Kostengünstig Inference (<€0.001/Antwort vs €0.01 bei GPT-4)
Cost: €200-500 (Training)
Verdict: ✅ Wirtschaftlich sinnvoll
Fine-Tuning Methoden im Vergleich
1. Full Fine-Tuning (klassisch)
Alle Gewichte des Modells werden trainiert:
Before After
Layer 1: [0.234, -0.512, ...] [0.245, -0.515, ...] (trainiert)
Layer 2: [0.891, 0.234, ...] [0.885, 0.240, ...] (trainiert)
Layer 3: [0.112, -0.444, ...] [0.118, -0.450, ...] (trainiert)
...
Anforderungen:
- GPU-RAM: Modell × 4 (für Gradient speicherung)
Llama 3 70B FP32 = 140 GB Full Fine-Tuning = 560 GB RAM → Unmöglich auf Consumer-Hardware!
Vorteile:
- Beste Qualität (alles kann sich anpassen)
- Keine Tricks/Workarounds nötig
Nachteile:
- Teuer (€10.000+)
- Langsam (Tage)
- Braucht massive Hardware
Use-Case: Nur für spezialisierte Unternehmen, die massive Budgets haben.
2. LoRA (Low-Rank Adaptation) — Die Revolution
Idee: Statt alle Gewichte zu trainieren, trainiere nur kleine "Delta-Matrizen".
Original Layer: Weight Matrix [4096 × 4096]
LoRA Delta: A [4096 × 8] + B [8 × 4096]
Total Trainable: 32K + 32K = 64K Parameter
vs Full Layer: 16M Parameter
→ 250× weniger Parameter!
Output = Original_Weight × input + LoRA_A @ LoRA_B × input
└─ unchanged ─┘ └──── gelernt ──────┘
Rank erklären:
Rank 8 (klein): 64K trainable params, schnell, weniger Kapazität
Rank 16 (mittel): 128K trainable params, Standard
Rank 32 (groß): 256K trainable params, bessere Qualität
Rank 64 (sehr groß): 512K trainable params, aber:
- Diminishing returns
- Langsamer
LoRA-Anforderungen:
Llama 3 70B FP32 + LoRA Rank 16:
Model: 140 GB (read-only)
LoRA Weights: ~50 MB
Optimizer State: ~35 GB
Gradients: ~35 GB
Total: ~140 GB + 70 GB (vs 560 GB Full Fine-Tuning!)
→ Passt auf RTX A6000 (48 GB) mit Tricks
Praktisch:
- Training: 2-4 Stunden auf RTX 4090
- Cost: €50-200
- Inference: Merge LoRA in Original (oder parallel nutzen)
Vorteile:
- 250× weniger Parameter
- Schnell und günstig
- Gut dokumentiert, viele Tools
Nachteile:
- Weniger Kapazität (nur Rank 16-32 trainierbar)
- Nicht für massive Stil-Änderungen geeignet
3. QLoRA (Quantized LoRA) — LoRA Turbo
Idee: LoRA + Quantisierung des Base-Modells.
Statt Modell in FP32 (140 GB) zu halten,
comprimiere auf INT4 (35 GB).
Dann trainiere LoRA darauf.
Total RAM für Training:
Model: 35 GB (INT4, read-only)
LoRA: 50 MB
Optimizer + Gradients: ~35 GB
Total: ~70 GB (könnte auf 24 GB mit Optimierungen)
→ Passt auf RTX 4090!
Trick: "NF4" (Natively Quantized Float 4-bit)
Statt einfach INT4 zu nehmen, quantisiere auf die
"natürlichen" Verteilungspunkte der Gewichte
→ Bessere Qualität mit gleicher Größe
Praktisch:
- Training: 1-2 Stunden auf RTX 4090 (schneller, kleine Modell!)
- Cost: €20-50
- Qualität: ~95% von Full Fine-Tuning
Vorteile:
- Läuft auf Consumer-GPU (24 GB)
- Schnell und billig
- Kleine Output (50 MB statt GB)
Nachteile:
- Etwas Qualitätsverlust durch Quantisierung
- Neuere Methode, weniger erprobt
4. DoRA (Decomposed Rank Adaptation)
Idee: Separate Magnitude + Direction Adaptation.
LoRA trainiert: A @ B
DoRA trainiert: m (magnitude) + A @ B (direction)
m × (A @ B) gibt mehr Flexibilität
Result: Bessere Qualität als reines LoRA bei gleichem Rank
Praktisch:
- Ähnliche RAM-Anforderung wie LoRA
- ~5-10% bessere Qualität
- Tools: Unsloth, Axolotl (mittlerweile)
5. Prefix Tuning / Prompt Tuning
Idee: Trainiere nur ein Präfix, das zu jedem Input geprepended wird.
Input: "Übersetze zu Englisch: Der Hund springt"
Prefix (trainierbar): [0.234, -0.512, ..., 0.891] (500 tokens)
↓
Combined: [prefix_vectors] + [input_embedding]
↓
LLM generiert: "The dog jumps"
Trainable Parameters: nur Prefix (~100K)
Vorteile:
- Extrem klein
- Keine Layer-interne Änderung nötig
Nachteile:
- Schlechtere Qualität als LoRA
- Token-Overhead (Präfix zählt zu Kontext)
Selten verwendet in der Praxis.
Praktisch: LoRA Training mit Unsloth
Setup (30 Sekunden)
pip install unsloth[colab-new] -q
Code-Beispiel
from unsloth import FastLanguageModel
import torch
from datasets import load_dataset
from trl import SFTTrainer
from transformers import TrainingArguments
# 1. Modell laden + LoRA attachen
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="unsloth/llama-2-7b-bnb-4bit",
max_seq_length=2048,
load_in_4bit=True, # QLoRA!
dtype=torch.float16,
)
model = FastLanguageModel.get_peft_model(
model,
r=16, # LoRA Rank
lora_alpha=16,
target_modules=["q_proj", "v_proj"], # Welche Layer
lora_dropout=0.05,
bias="none",
use_gradient_checkpointing=True,
random_state=42,
)
# 2. Dataset
dataset = load_dataset("json", data_files="examples.json")
# Format: [{"input": "...", "output": "..."}, ...]
# 3. Training
trainer = SFTTrainer(
model=model,
train_dataset=dataset["train"],
args=TrainingArguments(
per_device_train_batch_size=4,
gradient_accumulation_steps=4,
warmup_steps=100,
num_train_epochs=3,
learning_rate=2e-4,
fp16=not torch.cuda.is_bf16_supported(),
bf16=torch.cuda.is_bf16_supported(),
logging_steps=10,
output_dir="outputs",
optim="adamw_8bit",
weight_decay=0.01,
lr_scheduler_type="linear",
seed=42,
),
packing=True, # Schneller
max_seq_length=2048,
dataset_text_field="text",
)
trainer.train()
# 4. Speichern
model.save_pretrained("lora-weights")
tokenizer.save_pretrained("lora-weights")
Dauer: 1-2 Stunden auf RTX 4090 mit 10K Beispiele
Dataset-Vorbereitung
Format 1: Instruction-Output (SFT)
[
{
"instruction": "Erkläre Deep Learning",
"output": "Deep Learning ist ein Bereich..."
},
{
"instruction": "Was ist ein Transformer?",
"output": "Ein Transformer ist eine Architektur..."
}
]
Best-Practice:
- Minimum 100 Beispiele, besser 1000+
- Diverse Beispiele (verschiedene Längen, Teme)
- Hochwertig (nicht auto-generiert)
- 80% Train / 20% Test Split
Format 2: Chat-Format (DPO / RLHF)
[
{
"messages": [
{"role": "user", "content": "Erkläre X"},
{"role": "assistant", "content": "X ist..."}
]
}
]
Dataset-Größe Guidelines
| Ziel | Beispiele | Training-Zeit | Cost |
|---|---|---|---|
| Proof-of-Concept | 100 | 15 Min | €10 |
| Guter Stil | 500 | 45 Min | €30 |
| Solide Domain-Anpassung | 1000 | 1.5h | €50 |
| Professionell | 5000 | 4h | €150 |
| State-of-Art | 10000+ | 8h+ | €300+ |
Hyperparameter-Guide
Learning Rate:
Für LoRA (Rank 16): 2e-4 (größer als Full Fine-Tuning)
Für QLoRA: 2e-4 bis 5e-4
Für Full: 5e-5 (kleiner, da alles trainiert)
Warmup:
warmup_steps = 5-10% von Total Training Steps
Verhindert zu großen Sprung am Anfang
Epochs:
1-3 für große Datasets (>1000 Beispiele)
3-5 für kleine Datasets (<500)
"Overfitting Prevention": Early Stopping wenn Validation Loss nicht sinkt
Batch Size:
Full Fine-Tuning: 8-16 (RAM-begrenzt)
LoRA: 16-32 (oft möglich)
QLoRA: 32-64 (klein!)
Gradient Accumulation:
Wenn Batch Size zu klein:
gradient_accumulation_steps = 4
→ Effektive Batch Size = 8 × 4 = 32
Weight Decay:
0.01 (Default, Regularisierung)
Höher (0.1) = weniger Overfitting, aber weniger angepasst
Niedriger (0.001) = mehr Anpassung, Overfitting-Risk
LoRA Rank Selection:
r=4-8: Sehr klein, schnell, OK für kleine Änderungen
r=16: Standard, Balance Qualität/Speed
r=32-64: Für große Datasets oder intensive Anpassung
Häufige Probleme und Lösungen
Problem 1: Training divergiert (Loss wird NaN)
Symptome:
- Loss: 2.3 → 1.8 → 0.9 → NaN
- Modell macht nur Müll
Ursachen:
- Learning Rate zu hoch
- Gradient Explosion
Lösung:
- Learning Rate 50% reduzieren (2e-4 → 1e-4)
- Gradient Clipping: max_grad_norm=1.0
- Warmup Steps erhöhen
Problem 2: Overfitting (Training Loss sinkt, Validation stagniert)
Training Loss: 2.5 → 1.2 → 0.3 → 0.05 (fallend)
Validation Loss: 2.5 → 1.3 → 1.3 → 1.3 (stagniert)
Lösung:
- Early Stopping nach N Steps ohne Verbesserung
- Weight Decay erhöhen (0.01 → 0.05)
- Dropout erhöhen (lora_dropout: 0.05 → 0.1)
- Kleinere Rank (r=32 → r=16)
Problem 3: Trainiertes Modell hat Halluzinationen
Beispiel:
Input: "Erkläre Quantisierung"
Output: "Quantisierung ist wenn man Bananen..."
Ursachen:
- Zu agressives Training (zu wenig Regularisierung)
- Dataset-Qualität schlecht
- Learning Rate zu hoch
Lösung:
- Dataset-Qualität überprüfen (manuell prüfen)
- Epochs reduzieren (3 → 1)
- Weight Decay erhöhen
- Learning Rate reduzieren
Nach dem Training: Merging & Deployment
Option 1: LoRA Separieren (Modularer Ansatz)
Original Model: model.safetensors (140 GB)
LoRA Weights: adapter_model.safetensors (50 MB)
Inference:
- Lade Original
- Lade LoRA parallel
- Apply: output = original_output + lora_multiplier × delta_output
Vorteil: Mehrere LoRAs auf selben Model möglich
Nachteil: Höhere RAM-Anforderung beim Inference
Option 2: LoRA Mergen (Single Datei)
from peft import AutoPeftModelForCausalLM
model = AutoPeftModelForCausalLM.from_pretrained(
"path/to/lora_weights",
device_map="cpu",
torch_dtype=torch.float16,
)
merged_model = model.merge_and_unload()
merged_model.save_pretrained("merged-model")
Output: Neue Model-Datei ohne LoRA-Referenzen Vorteil: Einfacher zu deployen, keine LoRA-Kompatibilität nötig Nachteil: Nicht reversibel, größer (aber quantisierbar)
Kosten-Vergleich (2026 Realitäten)
| Methode | Training | Infer/1K Tokens | Speicher (70B) | Total für 1M Inferences |
|---|---|---|---|---|
| Fine-Tune + Deploy eigenes Modell | €200 | €0.001 | 70 GB | €201 |
| RAG + GPT-4 | €50 | €0.15 | 10 GB | €200+ |
| QLoRA + Deploy (vLLM) | €50 | €0.002 | 35 GB | €52 |
| GPT-4 API nur | €0 | €0.03 | 0 | €300 |
Fazit: Bei >100K Inferences / Monat → Fine-Tuning wirtschaftlich.
Fine-Tuning ist nicht immer nötig, aber wenn dein Domain sehr spezifisch ist und du Budget hast, ist QLoRA das Goldstandard. Training in <2 Stunden, Kosten <€100, Qualität >95% des Full Fine-Tuning.
