Verborgene Signale · Begleitseite ← Alle Aktivitäten DE·EN
Kapitel 7 · Das Symbionten-Werkzeug · Aktivität 7.3 · Master

Symbionten-Klassifikator

Vom Wortzählen zum Sprachmodell: Du erzeugst dir Trainingsdaten mit dem einfachen Verfahren, feintunst ein deutsches BERT darauf — und fängst den Egel dort, wo Wortlisten blind sind: bei der wiederholten Idee.

Dauer Projekt (GPU-Training 1–2 h) Schwierigkeit hoch Gruppe Master / Projekt Voraussetzung 7.1/7.2, Python, Colab-GPU M

Kurz gesagt

Was: Der Wortlisten-Ansatz aus dem Basisteil hat zwei Schwächen — er erkennt die stilistische Schmetterlings-Person nicht, und den Egel nur unzuverlässig. Denn dessen Signatur ist kein Wort, sondern die Wiederholung einer fremden Idee. Du treibst die Methode weiter: erst ein Sprachmodell feintunen, dann den Egel mit semantischer Ähnlichkeit fangen.

Der Kern-Gedanke: Weak Supervision. Statt mühsam von Hand zu etikettieren, lässt du den einfachen Wortzähler automatisch Pseudo-Labels erzeugen — ein grober „Lehrer“ — und trainierst damit ein viel feineres „Schüler“-Modell, das Bedeutung im Kontext versteht statt nur Wörter zu zählen.

Du brauchst: anonymisierte Chats (eigene Export-Dateien oder der Korpus im Repo), Python mit transformers, datasets und sentence-transformers, am besten auf einer Colab-GPU. Die vollständige Anleitung mit Trainingsdaten und Notebook liegt im Ordner kap07-master auf GitHub.

Worum es geht

Im Basisteil hast du fünf Rollen — Biene, Ameise, Schmetterling, Capybara, Egel — allein aus Wörtern gelesen. Das ist ein grobes Werkzeug: Wortlisten sind eine Hypothese, kein Verständnis. Jemand kann „Idee“ sagen, ohne kreativ zu sein, und sehr kreativ sein, ohne das Wort je zu benutzen. Bessere Verfahren — solche, die auf Sprachmodellen wie BERT beruhen — verstehen Bedeutung im Kontext. Genau eines davon baust du hier.

Und du löst das hartnäckigste Problem des Basisteils: den Egel. Bei Felix haben wir nur einen Hinweis bekommen (die Selbst-Positionierungs-Wörter), aber den eigentlichen Mechanismus übersehen — dass seine „Ideen“ inhaltlich Wiederholungen fremder Ideen sind. Um das zu erkennen, muss man Bedeutungs-Ähnlichkeit über die Zeit messen. Genau das leisten moderne Sprachmodelle.

Bevor du startest

Dieser Abschnitt richtet sich an fortgeschrittene Lesende mit Programmiererfahrung — im Master-Kurs an MIT, HSLU und der Universität zu Köln ist genau dieser Schritt der zentrale Lernanlass. Das Feintunen braucht eine GPU; nutze am einfachsten Google Colab (Laufzeit → GPU). Auf einer CPU läuft alles auch, dauert aber deutlich länger — dann verkleinere Datenmenge und Epochen.

Schritt 1 — Trainingsdaten mit dem einfachen Verfahren erzeugen

Wir sammeln 100 bis 500 anonymisierte Chats, wenden den Wortlisten-Klassifikator an und erhalten automatisch Pseudo-Labels. Nicht perfekt, aber gut genug als Lehrer-Modell.

# fuenf Rollen, je eine kleine Wortliste (aus dem Basisteil)
wortlisten = {
    "Biene":        ["idee", "stell dir vor", "was waere wenn", "koennten wir", "vorschlag"],
    "Ameise":       ["plan", "liste", "erledigt", "deadline", "wer macht", "organisiere"],
    "Schmetterling":["schoen", "fuehle", "wunderbar", "traum", "stimmung", "aesthetisch"],
    "Capybara":     ["passt", "kein stress", "egal", "entspannt", "alles gut", "gemuetlich"],
    "Egel":         ["meinen eltern", "hab ihr gezeigt", "beeindruckt von", "wie ich schon sagte"],
}

def wortliste_raten(text):
    text = text.lower()
    punkte = {rolle: sum(w in text for w in ws) for rolle, ws in wortlisten.items()}
    beste = max(punkte, key=punkte.get)
    return beste if punkte[beste] > 0 else None      # None = unsicher -> weglassen

# nachrichten = Liste vieler anonymisierter Chat-Zeilen (Strings)
pseudo = [(m, wortliste_raten(m)) for m in nachrichten]
pseudo = [(m, r) for m, r in pseudo if r is not None]   # nur sichere Labels behalten
print("Pseudo-Labels:", len(pseudo))

Schritt 2 — Ein deutsches BERT feintunen

Mit den Pseudo-Labels trainieren wir ein vortrainiertes Modell (gbert-base) auf die Symbionten-Klassifikation. Dank transformers sind das rund 30 Zeilen.

from datasets import Dataset
from transformers import (AutoTokenizer, AutoModelForSequenceClassification,
                          TrainingArguments, Trainer)

rollen = list(wortlisten)                       # feste Reihenfolge -> Zahlen
zu_id  = {r: i for i, r in enumerate(rollen)}

tok = AutoTokenizer.from_pretrained("deepset/gbert-base")
def kodieren(b): return tok(b["text"], truncation=True, padding="max_length", max_length=64)

ds = Dataset.from_dict({"text":  [m for m, _ in pseudo],
                        "label": [zu_id[r] for _, r in pseudo]})
ds = ds.map(kodieren, batched=True).train_test_split(test_size=0.2)

modell = AutoModelForSequenceClassification.from_pretrained(
    "deepset/gbert-base", num_labels=len(rollen))

args = TrainingArguments("gbert-symbiont", num_train_epochs=3,
                         per_device_train_batch_size=16, eval_strategy="epoch")
Trainer(modell, args, train_dataset=ds["train"], eval_dataset=ds["test"]).train()

# das feine Modell versteht jetzt Kontext, nicht nur Woerter
tests = tok(["Sollen wir das mal ganz anders denken?"], return_tensors="pt",
            truncation=True, padding=True)
print(rollen[int(modell(**tests).logits.argmax())])

Schritt 3 — Den Egel mit semantischer Ähnlichkeit fangen

Zusätzlich berechnen wir für jede Nachricht die semantische Ähnlichkeit zu allen früheren Beiträgen anderer Personen (mit Sentence-BERT). Wer regelmässig hoch-ähnliche Beiträge liefert, ohne zu zitieren, ist ein Egel-Kandidat.

from sentence_transformers import SentenceTransformer, util

sbert = SentenceTransformer("paraphrase-multilingual-MiniLM-L12-v2")

# chat = Liste (autor, text) in zeitlicher Reihenfolge
vektoren = sbert.encode([t for _, t in chat], convert_to_tensor=True)

for i, (autor, text) in enumerate(chat):
    frueher = [j for j in range(i) if chat[j][0] != autor]   # nur ANDERE, nur FRUEHER
    if not frueher:
        continue
    aehnlich = util.cos_sim(vektoren[i], vektoren[frueher])[0]
    hoechste = float(aehnlich.max())
    if hoechste > 0.70:                     # hohe Aehnlichkeit ohne Zitat -> Verdacht
        quelle = chat[frueher[int(aehnlich.argmax())]][0]
        print(f"Egel-Verdacht: {autor} wiederholt {quelle}  (Aehnlichkeit {hoechste:.2f})")

In Felix’ Fall markiert dieses Verfahren seinen Montag-18:42-Beitrag eindeutig als Übernahme von Miras Montag-14:03-Idee — genau die Übernahme, die die Wortliste übersehen hat.

Was du sehen solltest

Das feingetunte BERT trifft die Rollen deutlich zuverlässiger als die Wortliste — vor allem dort, wo dieselbe Absicht in ganz anderen Worten steckt. Und die Ähnlichkeits-Analyse hebt den Egel hervor, ohne dass ein einziges „verräterisches“ Wort nötig wäre. Zusammen zeigen beide, was ein Sprachmodell dem blossen Zählen voraushat: Es liest Bedeutung, nicht Buchstaben.

Arbeitsblatt

Vom Zählen zum Verstehen

  1. Weak Supervision: Wieso darf der grobe Wortzähler ein besseres Modell erziehen, obwohl er selbst Fehler macht? Wo liegt die Grenze dieser Idee?
  2. Suche eine Nachricht, die die Wortliste falsch einordnet, das feingetunte BERT aber richtig — und erkläre, warum der Kontext den Unterschied macht.
  3. Warum vergleichen wir jede Nachricht nur mit früheren Beiträgen anderer — nicht mit allen? Was würde sonst schiefgehen?
  4. Die 0,70-Schwelle ist willkürlich. Wie verändert eine höhere oder tiefere Schwelle die Zahl der Egel-Verdachtsfälle — und den Anteil falscher Alarme?
  5. Das Kernproblem (Schritt 4): Wer einen Gedanken unabhängig hat, sieht für das Modell aus wie ein Egel. Kann man aus Verhaltensdaten allein Übernahme von unabhängiger Konvergenz unterscheiden?
Lösung anzeigen

1. Weil das Schüler-Modell über viele Beispiele die verlässlichen Muster lernt und die zufälligen Fehler des Lehrers herausmittelt. Die Grenze: systematische Fehler des Lehrers (immer derselbe blinde Fleck) werden mitgelernt — Pseudo-Labels erben die Vorurteile der Wortliste.

2. Individuell. Typisch: „Sollen wir das mal ganz anders denken?“ enthält kein Wortlisten-Wort, ist aber klar eine Bienen-Idee. BERT erkennt die Absicht am Satzbau und Kontext, die Wortliste sieht nur unbekannte Wörter.

3. Nur frühere: Sonst würde eine Idee als Kopie ihrer eigenen späteren Wiederholung gelten — Ursache und Wirkung vertauscht. Nur andere: Sich selbst zu wiederholen ist kein Egel-Verhalten, sondern normal.

4. Höhere Schwelle → weniger Verdachtsfälle, aber echte Übernahmen werden übersehen; tiefere Schwelle → mehr Treffer, aber viele harmlose Themen-Überschneidungen als Fehlalarm. Es ist der übliche Kompromiss zwischen Genauigkeit und Vollständigkeit.

5. Aus Verhaltensdaten allein nicht sicher. Hohe Ähnlichkeit plus zeitliche Reihenfolge ist ein starker Hinweis, aber kein Beweis — zwei Menschen können unabhängig auf dasselbe kommen. Die Literatur zur Plagiats-Erkennung gibt darauf keine eindeutige Antwort; deshalb ist das Ergebnis ein Verdacht, kein Urteil.

Wenn's klemmt

ProblemWahrscheinliche Ursache & Lösung
CUDA out of memoryper_device_train_batch_size senken (z. B. 8) oder max_length kürzen. In Colab die GPU-Laufzeit wählen.
Training extrem langsamEs läuft auf der CPU. In Colab „Laufzeittyp ändern → GPU“; sonst Datenmenge und Epochen reduzieren.
Modell sagt immer dieselbe RollePseudo-Labels stark unausgewogen (Egel ist selten). Klassen ausbalancieren oder class_weight-Verlust nutzen.
eval_strategy unbekanntÄltere transformers-Version: dort heisst der Parameter evaluation_strategy.
Sentence-BERT lädt ewigDas Modell wird einmalig heruntergeladen; danach aus dem Cache. Beim ersten Mal Internet nötig.

Zum Nachdenken

Erweiterung

← 7.2 Die Prompt-Werkstatt 7.4 Beecome zur Analyse von Symbionten verwenden →