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.