Sofortantwort
Curriculum Learning einfach erklärt
Training von einfach zu schwer – wie ein strukturierter Lehrplan.
- Kurz gesagt
- Training beginnt mit einfachen Beispielen, Schwierigkeit steigt
- Typischer Einsatz
- NLP-Training, Computer Vision, Reinforcement Learning
- Wichtig zu wissen
- Erfordert Definition von 'Schwierigkeit' für die Daten
Curriculum Learning im Überblick
Curriculum Learning trainiert Modelle wie Schüler: Erst einfache Aufgaben, dann schrittweise schwierigere. Das kann Lernen stabilisieren oder beschleunigen, funktioniert aber nicht für jeden Task automatisch besser.
Random Training vs. Curriculum:
Random Training:
Epoch 1: [schwer, leicht, mittel, schwer, leicht, schwer, mittel...]
→ Modell kämpft mit schweren Beispielen von Anfang an
Curriculum Learning:
Epoch 1: [leicht, leicht, leicht, leicht...]
Epoch 2: [leicht, mittel, leicht, mittel...]
Epoch 3: [mittel, mittel, schwer, mittel...]
Epoch 4: [schwer, schwer, schwer, schwer...]
→ Modell baut Verständnis schrittweise auf
Warum funktioniert das?
| Aspekt | Random | Curriculum |
|---|---|---|
| Frühe Gradienten | können stark variieren | können stabiler sein |
| Konvergenz | taskabhängig | kann schneller sein |
| Lokale Minima | taskabhängig | kann helfen |
| Finale Qualität | baselineabhängig | kann besser sein |
Technisch betrachtet
Schwierigkeit definieren
Für Text/NLP:
def text_difficulty(text):
scores = []
# Länge
scores.append(len(text.split()) / reference_length)
# Vokabular-Komplexität
rare_words = count_rare_words(text)
scores.append(rare_words / len(text.split()))
# Syntaktische Komplexität
scores.append(count_clauses(text) / reference_clause_count)
return sum(scores) / len(scores)
Für Bilder:
def image_difficulty(image):
# Anzahl Objekte
num_objects = detect_objects(image)
# Verdeckung
occlusion_score = estimate_occlusion(image)
# Bildqualität
noise_level = estimate_noise(image)
return (num_objects * object_weight +
occlusion_score * occlusion_weight +
noise_level * noise_weight)
Model-basiert (Self-Paced Learning):
def model_based_difficulty(model, example):
# Schwierigkeit = Loss des aktuellen Modells
with torch.no_grad():
loss = model.compute_loss(example)
return loss.item()
Curriculum Sampler
class CurriculumSampler(torch.utils.data.Sampler):
def __init__(self, dataset, difficulty_fn, num_epochs, current_epoch):
self.dataset = dataset
self.current_epoch = current_epoch
self.num_epochs = num_epochs
# Schwierigkeit für alle Beispiele berechnen
self.difficulties = [
difficulty_fn(dataset[i])
for i in range(len(dataset))
]
def __iter__(self):
# Anteil der Daten basierend auf Epoche
progress = self.current_epoch / self.num_epochs
# Threshold für Schwierigkeit
threshold = np.percentile(
self.difficulties,
min(max_percentile, start_percentile + growth_range * progress)
)
# Nur Beispiele unter Threshold
indices = [
i for i, d in enumerate(self.difficulties)
if d <= threshold
]
random.shuffle(indices)
return iter(indices)
Training Loop
for epoch in range(num_epochs):
# Sampler mit aktuellem Fortschritt
sampler = CurriculumSampler(
dataset,
difficulty_fn,
num_epochs,
epoch
)
dataloader = DataLoader(dataset, sampler=sampler)
for batch in dataloader:
loss = model(batch)
loss.backward()
optimizer.step()
print(f"Epoch {epoch}: Using {len(sampler)} examples")
Varianten
Anti-Curriculum:
- Schwere Beispiele zuerst
- Kann bei manchen Tasks besser sein
- Modell lernt schwierige Patterns früh
Self-Paced Learning:
- Modell entscheidet selbst, was es lernen kann
- Beispiele mit niedrigem Loss werden bevorzugt
- Dynamisch während Training
Competence-based:
def competence(epoch, total_epochs, c0):
"""
Wie viel des Curriculums ist 'freigeschaltet'?
Startet bei c0, endet bei 1.0
"""
return min(1.0, c0 + (1 - c0) * (epoch / total_epochs) ** 2)
Wann Curriculum Learning?
| Szenario | Empfehlung |
|---|---|
| Begrenzte Compute-Ressourcen | kann Effizienz verbessern |
| Sehr schwieriger Task | kann Training stabilisieren |
| Viel Daten, viel Compute | Nutzen separat validieren |
| Schwierigkeit schwer zu definieren | Aufwand kritisch prüfen |