Was ist Fine-Tuning?
Fine-Tuning ist der Prozess, bei dem ein bereits vortrainiertes KI-Modell (wie GPT oder LLaMA) auf spezifische Daten oder Aufgaben weiter trainiert wird. Statt ein Modell von Grund auf zu trainieren, nutzt man das vorhandene Wissen und passt es gezielt an neue Anforderungen an.
💡 Analogie: Fine-Tuning ist wie ein Aufbaustudium – du baust auf vorhandenem Wissen auf und spezialisierst dich in einem bestimmten Bereich.
Fine-Tuning Methoden
Full Fine-Tuning
Alle Parameter des Modells werden angepasst
Vorteile:
- • Maximale Anpassungsfähigkeit
- • Beste Ergebnisse für spezifische Domänen
Nachteile:
- • Hoher Rechenaufwand
- • Risiko von Overfitting
Ideal für: Wenn du viele Daten und Rechenkapazität hast
LoRA (Low-Rank Adaptation)
Nur kleine Adapter-Schichten werden trainiert
Vorteile:
- • Sehr effizient
- • Weniger Speicherbedarf
- • Schnelles Training
Nachteile:
- • Etwas geringere Flexibilität
Ideal für: Ideale Balance zwischen Effizienz und Leistung
Prompt Tuning
Nur Prompt-Embeddings werden optimiert
Vorteile:
- • Minimal invasiv
- • Sehr schnell
- • Günstig
Nachteile:
- • Begrenzte Anpassungsmöglichkeiten
Ideal für: Für einfache Anpassungen mit wenig Ressourcen
1Umgebung einrichten
Installiere die erforderlichen Bibliotheken für modernes Fine-Tuning:
# Grundlegende Bibliotheken installieren
pip install transformers==4.40.0
pip install peft==0.11.0
pip install bitsandbytes==0.43.0
pip install accelerate==0.30.0
pip install trl==0.8.6
pip install datasets==2.19.0
# Für bessere Performance (optional)
pip install unsloth[cu121] # CUDA 12.1
pip install flash-attn --no-build-isolation
2Daten vorbereiten
Erstelle ein Dataset im ChatML-Format für optimale Ergebnisse:
import json
from datasets import Dataset
def prepare_dataset(data_file):
"""Bereite Dataset für Fine-Tuning vor"""
conversations = []
with open(data_file, 'r', encoding='utf-8') as f:
data = json.load(f)
for item in data:
conversation = [
{"role": "system", "content": "Du bist ein hilfreicher Assistent."},
{"role": "user", "content": item["instruction"]},
{"role": "assistant", "content": item["response"]}
]
conversations.append({"messages": conversation})
return Dataset.from_list(conversations)
3Modell konfigurieren
Lade das Basismodell mit QLoRA-Quantisierung:
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
BitsAndBytesConfig,
TrainingArguments
)
from peft import LoraConfig, get_peft_model
import torch
# QLoRA Konfiguration für 4-bit Training
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16
)
# Modell laden
model_name = "meta-llama/Llama-3.2-8B"
model = AutoModelForCausalLM.from_pretrained(
model_name,
quantization_config=bnb_config,
device_map="auto",
torch_dtype=torch.bfloat16,
attn_implementation="flash_attention_2"
)
# Tokenizer vorbereiten
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"
4LoRA konfigurieren
Optimale LoRA-Einstellungen für 2025:
from peft import LoraConfig, TaskType
# Moderne LoRA Konfiguration
peft_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
inference_mode=False,
r=16, # Rank - höher für komplexere Aufgaben
lora_alpha=16, # Alpha scaling parameter
lora_dropout=0.1,
# Alle linearen Schichten anvisieren
target_modules=[
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"
],
bias="none",
use_rslora=True, # 2025 Verbesserung
use_dora=False # Alternative zu LoRA
)
# LoRA auf Modell anwenden
model = get_peft_model(model, peft_config)
model.print_trainable_parameters()
# Ausgabe: trainable params: 6,738,432 || all params: 8,030,261,248 || trainable%: 0.08
5Training konfigurieren
Optimale Hyperparameter für verschiedene Hardware-Setups:
from trl import SFTTrainer, DataCollatorForCompletionOnlyLM
# Training Argumente - optimiert für RTX 4090/24GB
training_args = TrainingArguments(
output_dir="./llama-3.2-8b-fine-tuned",
per_device_train_batch_size=1,
gradient_accumulation_steps=8,
num_train_epochs=3,
learning_rate=2e-4,
lr_scheduler_type="cosine",
warmup_ratio=0.1,
logging_steps=10,
save_strategy="epoch",
evaluation_strategy="epoch",
save_total_limit=2,
bf16=True,
gradient_checkpointing=True,
dataloader_pin_memory=False,
max_grad_norm=1.0,
group_by_length=True,
ddp_find_unused_parameters=False
)
6Training ausführen
Vollständiges Training-Skript:
def format_chat_template(row):
"""Formatiere Daten für Chat-Template"""
messages = row['messages']
return tokenizer.apply_chat_template(messages, tokenize=False)
def main():
# Dataset laden
train_dataset = prepare_dataset("train_data.json")
eval_dataset = prepare_dataset("eval_data.json")
# Trainer initialisieren
trainer = SFTTrainer(
model=model,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
peft_config=peft_config,
tokenizer=tokenizer,
args=training_args,
max_seq_length=2048,
packing=True, # Effizientere GPU-Nutzung
formatting_func=format_chat_template
)
# Training starten
print("Training läuft...")
trainer.train()
# Modell speichern
trainer.save_model()
tokenizer.save_pretrained("./llama-3.2-8b-fine-tuned")
print("Training abgeschlossen!")
if __name__ == "__main__":
main()
7Evaluation und Test
Teste dein fine-getuntes Modell:
from peft import AutoPeftModelForCausalLM
import torch
# Fine-getuntes Modell laden
model = AutoPeftModelForCausalLM.from_pretrained(
"./llama-3.2-8b-fine-tuned",
device_map="auto",
torch_dtype=torch.bfloat16
)
tokenizer = AutoTokenizer.from_pretrained("./llama-3.2-8b-fine-tuned")
def generate_response(prompt, max_length=512):
"""Generiere Antwort mit fine-getunetem Modell"""
messages = [
{"role": "system", "content": "Du bist ein hilfreicher Assistent."},
{"role": "user", "content": prompt}
]
# Formatiere mit Chat-Template
formatted_prompt = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
# Tokenisiere und generiere
inputs = tokenizer(formatted_prompt, return_tensors="pt").to(model.device)
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=max_length,
temperature=0.7,
do_sample=True,
top_p=0.95,
pad_token_id=tokenizer.eos_token_id
)
# Dekodiere Antwort
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
return response.split("assistant")[-1].strip()
# Teste verschiedene Prompts
test_prompts = [
"Erkläre mir künstliche Intelligenz in einfachen Worten.",
"Was sind die Vorteile von Fine-Tuning?",
"Wie funktioniert LoRA?"
]
for prompt in test_prompts:
print(f"\nPrompt: {prompt}")
response = generate_response(prompt)
print(f"Antwort: {response}")
Hardware-Anforderungen (2025)
Modellgröße | Minimale GPU | Empfohlene GPU | Trainingsdauer |
---|---|---|---|
7B Parameter | RTX 3090 (24GB) | RTX 4090 (24GB) | 2-6 Stunden |
13B Parameter | A100 (40GB) | H100 (80GB) | 4-12 Stunden |
70B Parameter | 2x A100 (80GB) | 4x H100 (80GB) | 1-3 Tage |