Zum Hauptinhalt springen

Top k

Top k ist ein Sampling-Parameter, der die Textgenerierung auf die k wahrscheinlichsten Tokens beschränkt. Fan et al. (2018) zeigten, dass diese Methode dabei hilft, unwahrscheinliche oder unsinnige Ausgaben zu vermeiden und gleichzeitig kreativere Texte als Beam Search erzeugt.

1. Was ist Top k?

Top k begrenzt die Auswahl der nächsten Tokens auf eine feste Anzahl der wahrscheinlichsten Kandidaten. Holtzman et al. (2019) betonen, dass im Gegensatz zu Top p (Nucleus Sampling), das dynamisch basierend auf der Wahrscheinlichkeitsverteilung arbeitet, Top k eine statische Begrenzung ist.

Einfach erklärt: Wenn Top k = 50 ist, betrachtet die KI nur die 50 wahrscheinlichsten nächsten Wörter und ignoriert alle anderen, egal wie die Wahrscheinlichkeitsverteilung aussieht.

1.1 Visualisierung des Konzepts

Beispiel für "Das Wetter ist heute...":

RangTokenWahrscheinlichkeitBei k=3Bei k=5
1schön0.35
2sonnig0.20
3bewölkt0.15
4regnerisch0.10
5windig0.08
6stürmisch0.05
.........

2. Interaktive Top-k Demo

Top-k Live Demo

Experimentiere mit verschiedenen Top-k-Werten und beobachte, wie sie die Token-Auswahl bei der Textgenerierung beeinflussen

Aktueller Wert: 401 - 100

Effekt bei 40:

Ausgewogene Auswahl

Beispiel-Ausgabe:

Klicke auf "Generieren" um eine Beispiel-Ausgabe mit dem aktuellen Parameter-Wert zu sehen

3. Technische Details

3.1 Der Top k Algorithmus

  1. Berechne die Wahrscheinlichkeiten für alle möglichen nächsten Tokens
  2. Sortiere die Tokens nach Wahrscheinlichkeit (absteigend)
  3. Behalte nur die ersten k Tokens
  4. Normalisiere die Wahrscheinlichkeiten der verbleibenden Tokens
  5. Wähle aus diesen k Tokens basierend auf ihrer relativen Wahrscheinlichkeit
def top_k_sampling(logits, k):
    """
    Wendet Top-k Sampling auf die Logits an
    """
    # Sortiere und behalte nur die k größten Werte
    top_k_logits, top_k_indices = torch.topk(logits, k=k, dim=-1)
    
    # Setze alle anderen Logits auf -infinity
    logits_masked = torch.full_like(logits, float('-inf'))
    logits_masked.scatter_(-1, top_k_indices, top_k_logits)
    
    # Wende Softmax an für Wahrscheinlichkeiten
    probs = torch.softmax(logits_masked, dim=-1)
    
    return probs

4. Top k vs. Top p

Zhao et al. (2024) erklären in ihrer umfassenden LLM-Übersicht, dass die beiden Methoden unterschiedliche Stärken und Schwächen haben:

EigenschaftTop kTop p
Anzahl TokensFest (immer k)Variabel
Anpassung an VerteilungNeinJa
Bei flacher VerteilungKann zu restriktiv seinPasst sich an
Bei steiler VerteilungKann unnötige Tokens einschließenWählt nur relevante
VorhersagbarkeitHochMittel

4.1 Praktischer Vergleich

Szenario 1: Eindeutige Antwort

Frage: "Die Hauptstadt von Deutschland ist..."

  • Berlin: 95% Wahrscheinlichkeit
  • Andere Tokens: jeweils unter 1%

→ Top k=50 würde 49 unnötige Tokens berücksichtigen

→ Top p=0.9 würde nur "Berlin" wählen

Szenario 2: Viele mögliche Antworten

Frage: "Zum Frühstück esse ich gerne..."

  • Viele Optionen mit ähnlichen Wahrscheinlichkeiten (2-5%)

→ Top k=10 könnte gute Optionen ausschließen

→ Top p=0.9 würde mehr Vielfalt zulassen

5. Wann solltest du Top k verwenden?

5.1 Geeignete Anwendungsfälle

  • Kontrollierte Kreativität: Wenn du Vielfalt willst, aber Grenzen setzen möchtest
  • Vermeidung seltener Tokens: Um ungewöhnliche oder fehlerhafte Ausgaben zu verhindern
  • Konsistente Performance: Wenn die Rechenlast vorhersagbar sein soll
  • Spezielle Domänen: Bei Fachsprache mit begrenztem Vokabular

5.2 Empfohlene k-Werte

Anwendungsfallk-WertBegründung
Greedy Decoding1Immer das wahrscheinlichste Token
Faktenbasierte Antworten5-10Wenig Variation, hohe Genauigkeit
Allgemeine Konversation40-50Ausgewogene Vielfalt
Kreatives Schreiben100-200Maximale Kreativität mit Grenzen

6. Praktische Code-Beispiele

6.1 Anthropic Claude

import anthropic

client = anthropic.Anthropic()

# Top k für kontrollierte Kreativität
response = client.messages.create(
    model="claude-3-opus-20240229",
    max_tokens=1000,
    top_k=40,  # Nur die 40 wahrscheinlichsten Tokens
    messages=[{
        "role": "user",
        "content": "Schreibe einen kurzen Dialog zwischen zwei Charakteren"
    }]
)

# Sehr niedriges k für präzise Antworten
precise_response = client.messages.create(
    model="claude-3-opus-20240229",
    max_tokens=100,
    top_k=5,
    messages=[{
        "role": "user",
        "content": "Was ist die Quadratwurzel von 144?"
    }]
)

6.2 Google Gemini mit Top k und Top p

import google.generativeai as genai

genai.configure(api_key="YOUR_API_KEY")
model = genai.GenerativeModel('gemini-pro')

# Kombination von Top k und Top p
generation_config = genai.types.GenerationConfig(
    top_k=100,   # Erste Filterung: Top 100 Tokens
    top_p=0.8,   # Zweite Filterung: 80% Wahrscheinlichkeitsmasse
    temperature=0.7
)

response = model.generate_content(
    "Erkläre Machine Learning in einfachen Worten",
    generation_config=generation_config
)

# Nur Top k ohne Top p
strict_config = genai.types.GenerationConfig(
    top_k=10,
    top_p=1.0,  # Deaktiviert Top p
    temperature=0.5
)

response = model.generate_content(
    "Liste die Planeten unseres Sonnensystems auf",
    generation_config=strict_config
)

6.3 Vergleichstest verschiedener k-Werte

# Test mit verschiedenen k-Werten
k_values = [1, 5, 20, 50, 100]
prompt = "Ein kreativer Name für ein Café wäre"

results = {}
for k in k_values:
    response = client.messages.create(
        model="claude-3-opus-20240229",
        max_tokens=20,
        top_k=k,
        messages=[{"role": "user", "content": prompt}]
    )
    results[k] = response.content[0].text
    
# Ausgabe der Ergebnisse
for k, result in results.items():
    print(f"k={k}: {result}")
    
# Mögliche Ausgabe:
# k=1: "Kaffeepause"  (immer dasselbe)
# k=5: "Bohnenglück"
# k=20: "Traumtasse & Co."
# k=50: "Der verzauberte Löffel"
# k=100: "Wolke 7 - Kaffee & Poesie"

7. API-Verfügbarkeit

AnbieterVerfügbarStandardwertBesonderheiten
OpenAI-Nicht direkt verfügbar, nur Top p
Anthropic ClaudeKein DefaultFür fortgeschrittene Nutzer empfohlen
Google Gemini40Kombinierbar mit Top p
Cohere0 (deaktiviert)Als "k" Parameter
Hugging Face50Standard in Transformers
MistralVariiertModellabhängig

8. Fortgeschrittene Techniken

8.1 Adaptive k-Werte

Chung et al. (2023) arbeiten an Methoden zur Verbesserung der Diversität bei gleichzeitiger Genauigkeit. Manche Systeme passen k dynamisch an den Kontext an:

def get_adaptive_k(prompt_type, confidence_threshold=0.8):
    """
    Passt k basierend auf dem Prompt-Typ und der
    Konfidenz der Top-Tokens an
    """
    base_k_values = {
        "factual": 10,
        "creative": 100,
        "code": 20,
        "conversation": 50
    }
    
    # Analysiere die Wahrscheinlichkeitsverteilung
    # Wenn Top-Token sehr wahrscheinlich, reduziere k
    # Wenn Verteilung flach, erhöhe k
    
    return adjusted_k

8.2 Kombinationsstrategien

Bei Google Gemini kann die Reihenfolge von Top k und Top p wichtig sein:

# Strategie 1: Erst k, dann p (Google Gemini Standard)
# 1. Filtere auf Top 50 Tokens
# 2. Davon nimm die, die 90% Wahrscheinlichkeit abdecken

config_k_then_p = {
    "top_k": 50,
    "top_p": 0.9
}

# Strategie 2: Nur k für harte Begrenzung
config_only_k = {
    "top_k": 30,
    "top_p": 1.0  # Deaktiviert
}

# Strategie 3: Niedriges k mit hohem p
# Für fokussierte aber nicht zu repetitive Ausgaben
config_balanced = {
    "top_k": 20,
    "top_p": 0.95
}

9. Debugging und Optimierung

9.1 Häufige Probleme und Lösungen

⚠️ Problem: Zu repetitive Ausgaben

Symptom: Die KI wiederholt sich ständig

Lösung: Erhöhe k von z.B. 10 auf 40-50

⚠️ Problem: Unsinnige oder inkohärente Ausgaben

Symptom: Unerwartete oder unpassende Wörter

Lösung: Reduziere k auf 20-30

⚠️ Problem: Keine Variation bei mehreren Anfragen

Symptom: Gleiche Ausgabe bei gleicher Eingabe

Lösung: k=1 ist zu niedrig, erhöhe auf mindestens 5

9.2 Test-Framework für optimale k-Werte

def test_k_values(prompt, k_range, num_samples=5):
    """
    Testet verschiedene k-Werte und bewertet die Ausgaben
    """
    results = []
    
    for k in k_range:
        outputs = []
        for _ in range(num_samples):
            response = generate_with_k(prompt, k)
            outputs.append(response)
        
        # Bewerte Vielfalt
        diversity = calculate_diversity(outputs)
        
        # Bewerte Kohärenz
        coherence = calculate_coherence(outputs)
        
        results.append({
            'k': k,
            'diversity': diversity,
            'coherence': coherence,
            'samples': outputs
        })
    
    return results

# Verwendung
k_range = [5, 10, 20, 40, 80, 160]
results = test_k_values(
    "Schreibe einen Slogan für ein Umweltprojekt",
    k_range
)

# Finde optimales k
optimal_k = find_optimal_k(results, 
    diversity_weight=0.6, 
    coherence_weight=0.4
)

10. Best Practices

Li et al. (2024) zeigen in ihrer Arbeit zur Verbesserung linguistischer Diversität, dass die richtige Wahl von Sampling-Parametern entscheidend ist:

  1. Starte mit Standardwerten: k=40 ist oft ein guter Ausgangspunkt
  2. Teste iterativ: Passe k basierend auf den Ergebnissen an
  3. Berücksichtige den Kontext: Verschiedene Aufgaben brauchen verschiedene k-Werte
  4. Kombiniere mit anderen Parametern: Top k + Temperature kann effektiver sein als nur ein Parameter
  5. Dokumentiere deine Werte: Halte fest, welche k-Werte für welche Aufgaben funktionieren