Skip to content
Guides6 min read

Jenseits der vollständigen Überlappung: adaptive Annotator-Abdeckung für große Datensätze

Alles doppelt zu labeln ist teuer; alles nur einfach zu labeln macht blind. Mit Potato 2.6 weisen Sie den meisten Items einen Annotator zu und einer stratifizierten Stichprobe drei – samt adaptiver Verstärkung und automatischem Adjudikations-Routing.

Potato Team

In jedem Annotationsprojekt von einiger Größe gibt es eine wiederkehrende Spannung. Bekommt jedes Item zwei oder drei Annotatoren, können Sie die Übereinstimmung messen und Ihren Labels vertrauen, doch Sie haben Ihr Budget gerade verdoppelt oder verdreifacht. Bekommt jedes Item nur einen Annotator, labeln Sie für dasselbe Geld dreimal so viele Daten und haben keine Ahnung, wie verlässlich auch nur eines davon ist.

Der übliche Kompromiss ist jedem vertraut, der schon einmal eine Studie durchgeführt hat: den Großteil des Korpus einfach annotieren und eine kleine Stichprobe doppelt oder dreifach annotieren, um die Qualität im Blick zu behalten. Das Problem war immer, das Werkzeug dazu zu bringen, das sauber zu erledigen, und dann mit der Überlappung auch etwas anzufangen, sobald man sie hat. Potato 2.6 baut dieses Design fest ein – über zwei Konfigurationsblöcke (num_annotators_per_item und per_annotator_quota) sowie adaptive Verstärkung und Adjudikations-Routing.

Dieser Beitrag führt durch das Abdeckungsdesign, vom einfachen Fall bis zum adaptiven. Die Dokumentation zur heterogenen Abdeckung enthält die vollständige Referenz.

Standardmäßige Einfachabdeckung, eine stratifizierte Überlappungsstichprobe mit drei Annotatoren, adaptive Verstärkung bei Uneinigkeit und Adjudikations-RoutingAdaptive Annotator-Abdeckung in Potato

Obergrenzen pro Item mit einer Überlappungsstichprobe

num_annotators_per_item akzeptiert eine einzelne Ganzzahl als einheitliche Obergrenze oder ein strukturiertes Mapping, wenn Sie verschiedene Items unterschiedlich abdecken möchten. Die übliche Form ist ein Standardwert von eins, mit einer stratifizierten Stichprobe, die auf drei angehoben wird:

yaml
num_annotators_per_item:
  default: 1
  overlap_sample:
    fraction: 0.1
    count: 3
    stratify_by: domain
    seed: 42
  min: 1

Der Block overlap_sample hebt die Obergrenze für eine deterministische Teilmenge von Items an. Die Stichprobenziehung erfolgt einmalig beim Start, und die ausgewählten Items werden intern markiert, sodass die Zuweisungslogik sie fortan als hochabgedeckt behandelt. Die Felder sind unkompliziert: fraction ist der gezogene Anteil, count ist die angehobene Obergrenze (sie muss den Standardwert übersteigen) und seed macht die Auswahl über Neustarts hinweg reproduzierbar.

Das Detail, bei dem es sich zu verweilen lohnt, ist stratify_by. Richten Sie es auf ein Feld in Ihren Daten (hier domain), und der Anteil wird pro Schicht angewandt statt über den gesamten Pool. Jede Kategorie trägt anteilig zur Überlappungsstichprobe bei, sodass Sie die Übereinstimmung nicht an einer Stichprobe messen, die zufällig zu 90 % aus einer einzigen Domäne besteht. Mischt Ihr Korpus Nachrichten, soziale Medien und klinische Texte, taucht jedes davon in der Qualitätsstichprobe im Verhältnis zu seiner Größe auf.

Adaptive Verstärkung: mehr ausgeben, wo es schwierig wird

Eine feste Überlappungsstichprobe wird blind gewählt, bevor irgendjemand etwas annotiert hat. Doch die Items, die einen zweiten und dritten Blick am dringendsten brauchen, sind jene, bei denen die Annotatoren tatsächlich uneins sind – und welche das sind, erfahren Sie erst nach dem ersten Durchgang. Genau das übernimmt die adaptive Verstärkung:

yaml
num_annotators_per_item:
  default: 1
  adaptive:
    enabled: true
    disagreement_threshold: 0.5
    boost_to: 3

Sobald ein Item mindestens zwei Annotationen hat und sein Uneinigkeitswert disagreement_threshold überschreitet, wird seine Obergrenze auf boost_to angehoben und das Item kehrt für einen weiteren Durchgang in die Zuweisungswarteschlange zurück. Die Verstärkung erfolgt pro Item einmalig, sodass ein strittiges Item eine einzige Eskalation erhält, statt sich aufzuschaukeln. Das ist eine Abdeckung, die der Schwierigkeit der Daten folgt, statt sie im Voraus zu erraten.

Quoten pro Annotator

Abdeckungsobergrenzen steuern, wie viele Annotatoren jedes Item erhält. Ein separater Block steuert, wie viele Items jeder Annotator erhält – was Sie üblicherweise nach Fachkenntnis oder Vertrag variieren möchten:

yaml
per_annotator_quota:
  default: 100
  by_user:
    alice: 30
  by_user_role:
    expert: 30
    novice: 200
 
user_roles:
  alice: expert
  carol: novice

Die Auflösung läuft vom Spezifischsten zuerst: by_user[uid], dann by_user_role[user_roles[uid]], dann default. So können Sie einen bestimmten Experten auf 30 Items begrenzen, jeden anderen Experten per Rolle auf 30 und Anfänger auf 200, ohne dass die beiden Systeme mit den obigen Obergrenzen pro Item ins Gehege kommen.

Überlappung in eine Entscheidung verwandeln

Überlappung zu sammeln ist nur die halbe Arbeit; der Punkt ist, auf die Uneinigkeiten zu reagieren. Mit aktiviertem Adjudikationsblock werden Überlappungsstichproben-Items, die ihre Obergrenze erreichen, automatisch bewertet und in eine Adjudikationswarteschlange geschoben, sobald die Übereinstimmung unter Ihren Schwellenwert fällt:

yaml
adjudication:
  enabled: true
  adjudicator_users: [admin]
  min_annotations: 2
  agreement_threshold: 0.75

Der Effekt: Items mit geringer Übereinstimmung treten genau in dem Moment zutage, in dem die Stichprobe gesättigt ist, statt darauf zu warten, dass sich jemand erinnert, die Warteschlange von Hand neu aufzubauen. Ein Adjudikator öffnet die Warteschlange und sieht die wirklich strittigen Items, bereits aus der Masse herausgefiltert, in der sich alle einig waren.

Die Übereinstimmung lesen

Sobald die Überlappungsstichproben-Items gesättigt sind, stehen die Übereinstimmungsstatistiken unter /admin/iaa zur Verfügung. Der Endpunkt berechnet die für den Typ jedes Schemas passende Metrik, statt allem eine einzige Zahl aufzuzwingen: Cohens und Fleiss' Kappa für nominale Schemata, weighted kappa für ordinale und Token-Level-Kappa plus span F1 für Spans. Das ist wichtig, denn ein κ, das berechnet wird, als wären Ihre ordinalen Likert-Bewertungen ungeordnete Kategorien, würde die tatsächliche Übereinstimmung unterschätzen.

Zum Ausprobieren

Mit dem Release wird eine lauffähige Demonstration ausgeliefert. Vom Repository-Stamm aus:

bash
python potato/flask_server.py start examples/advanced/heterogeneous-coverage/config.yaml -p 8000

Sie verwendet 20 Items aus zwei Domänen, zieht 20 % für eine nach Domäne stratifizierte Drei-Annotatoren-Überlappung, aktiviert eine adaptive Verstärkung bei einem Schwellenwert von 0,5, definiert zwei Fachkenntnis-Stufen und routet Items mit geringer Übereinstimmung in die Adjudikation: das gesamte obige Design, von Anfang bis Ende.

Die Gestalt eines guten Abdeckungsplans

Zusammengenommen lässt das Design Sie entscheiden, wohin Ihr Annotationsbudget fließt, statt es gleichmäßig zu verteilen. Die meisten Items bekommen einen Durchgang. Ein stratifiziertes Stück bekommt drei, sodass Sie die Verlässlichkeit über das gesamte Korpus berichten können und nicht nur über eine Ecke davon. Items, die sich als wirklich schwierig erweisen, werden automatisch eskaliert, und die strittigen werden an einen Adjudikator geroutet. Sie geben am meisten für die unsichersten Daten aus und können jede Abdeckungsentscheidung in einem Methodenteil verteidigen.

Wie viele Annotatoren Sie für eine bestimmte Aufgabe tatsächlich brauchen, ist eine eigene Frage; der Beitrag wie viele Annotatoren Sie brauchen arbeitet die Faustregeln durch. Bei diesem Release geht es darum, jede Antwort, zu der Sie gelangen, leicht ausdrückbar zu machen. Die heterogene Abdeckung wird in Potato 2.6 ausgeliefert; siehe die Dokumentation zur heterogenen Abdeckung und die Referenz zur Aufgabenzuweisung für alles, was die obigen Blöcke können.