Qualitätskontrolle bei Annotation per Crowdsourcing
Bewährtes Vorgehen, um die Qualität in Annotationsprojekten zu sichern, samt praktischer Strategien, die du in Potato und darüber hinaus umsetzen kannst.
Qualitätskontrolle entscheidet darüber, ob am Ende brauchbare Annotationen stehen oder Rauschen. Dieser Leitfaden beschreibt Strategien, die sich in der Praxis bewähren, für Projekte per Crowdsourcing ebenso wie für Teams im Haus. Die Funktionen dahinter stehen in der Dokumentation zur Qualitätskontrolle.
Qualitätskontrolle über den Projektverlauf
Überblick über die Qualitätskontrolle
Keine einzelne Prüfung reicht für sich allein, deshalb kombinieren die meisten Projekte mehrere:
- Aufmerksamkeitstests: prüfen, ob die Annotierenden bei der Sache sind
- Redundanz: mehrere Annotationen pro Item einsammeln
- Übereinstimmungsmaße: die Konsistenz zwischen Annotierenden messen
- Schulung und Richtlinien: sicherstellen, dass die Aufgabe verstanden wurde
- Manuelle Durchsicht: Stichproben ziehen und die Annotationsqualität prüfen
Aufmerksamkeitstests über Surveyflow
Potato unterstützt einfache Aufmerksamkeitstests über das Surveyflow-System. Zwischen Annotationsblöcken kannst du Umfrageseiten einschieben, auf denen die Annotierenden bestätigen, dass sie aufmerksam sind.
annotation_task_name: "Sentiment Annotation with Checks"
surveyflow:
on: true
order:
- survey_instructions
- annotation
- survey_attention_check
- annotation
- survey_completionDefiniere die Fragen des Aufmerksamkeitstests als Umfrageseite:
# In your surveyflow survey definitions
survey_attention_check:
- question: "To confirm you're paying attention, please select 'Strongly Agree'."
type: radio
options:
- Strongly Disagree
- Disagree
- Neutral
- Agree
- Strongly AgreeWas Potato von Haus aus an Aufmerksamkeitstests mitbringt, ist begrenzt. Wenn du automatisch erkennen willst, wer durchfällt, und solche Personen aus der Aufgabe nehmen möchtest, brauchst du Skripte für die Nachbearbeitung oder die Qualitätsfunktionen deiner Crowdsourcing-Plattform.
Redundanz: mehrere Annotationen pro Item
Mehrere Annotationen pro Item einzusammeln gehört zu den verlässlicheren Methoden der Qualitätskontrolle. Konfiguriert wird das beim Aufsetzen der Daten:
annotation_task_name: "Multi-Annotator Sentiment Task"
data_files:
- path: data.json
list_as_text: false
sampling: random
# Control how many annotators see each item through assignment logic
# This is typically managed through your annotator assignment systemAuf Crowdsourcing-Plattformen wie Prolific kannst du:
- denselben HIT mehrfach ausspielen, um redundante Annotationen zu bekommen
- unterschiedliche Gruppen von Arbeitenden auf dieselben Daten ansetzen
- eine eigene Zuweisungslogik in deiner Datenpipeline umsetzen
Inter-Annotator-Übereinstimmung messen
Potato berechnet die Übereinstimmung für dich. Setz agreement_metrics: enabled: true, und Krippendorffs Alpha erscheint im Admin-Dashboard, sobald Annotationen eingehen. Der folgende Code lohnt sich trotzdem zu kennen, für die Fälle, in denen du ein Maß brauchst, das Potato nicht ausgibt, oder einen exportierten Datensatz auswertest:
Cohens Kappa (zwei Annotierende)
Für kategoriale Annotationen mit zwei Annotierenden:
from sklearn.metrics import cohen_kappa_score
# After collecting annotations
annotator1_labels = ["Positive", "Negative", "Positive", ...]
annotator2_labels = ["Positive", "Negative", "Neutral", ...]
kappa = cohen_kappa_score(annotator1_labels, annotator2_labels)
print(f"Cohen's Kappa: {kappa:.3f}")Fleiss' Kappa (mehrere Annotierende)
Ab drei annotierenden Personen:
from statsmodels.stats.inter_rater import fleiss_kappa
import numpy as np
# Build a matrix of label counts per item
# Each row is an item, each column is a label category
ratings_matrix = np.array([
[3, 0, 0], # Item 1: 3 Positive, 0 Negative, 0 Neutral
[2, 1, 0], # Item 2: 2 Positive, 1 Negative, 0 Neutral
[0, 0, 3], # Item 3: 0 Positive, 0 Negative, 3 Neutral
...
])
kappa = fleiss_kappa(ratings_matrix)
print(f"Fleiss' Kappa: {kappa:.3f}")Hinweise zur Interpretation
| Kappa-Wert | Interpretation |
|---|---|
| < 0,20 | geringe Übereinstimmung |
| 0,21 - 0,40 | mäßige Übereinstimmung |
| 0,41 - 0,60 | mittlere Übereinstimmung |
| 0,61 - 0,80 | deutliche Übereinstimmung |
| 0,81 - 1,00 | nahezu perfekte Übereinstimmung |
Potato unterstützt Aufmerksamkeitstests, Gold-Items und das Verfolgen der Inter-Annotator-Übereinstimmung, um die Annotationsqualität zu halten:

Items als Goldstandard
Goldstandards sind vorab gelabelte Items mit bekannter richtiger Antwort, die du unter deine Daten mischst. An ihnen erkennst du, wer rät oder unaufmerksam arbeitet.
Gold-Items anlegen
- Stell eine Menge Items zusammen, deren richtige Antwort eindeutig ist
- Lass diese Items von Fachleuten labeln
- Misch sie unter deine regulären Annotationsdaten
[
{
"id": "gold_001",
"text": "I absolutely love this product! Best purchase ever!",
"is_gold": true,
"gold_label": "Positive"
},
{
"id": "gold_002",
"text": "This is terrible. Complete waste of money. Worst experience.",
"is_gold": true,
"gold_label": "Negative"
},
{
"id": "regular_001",
"text": "The product arrived on time and works as expected.",
"is_gold": false
}
]Leistung auf den Gold-Items auswerten
Wenn die Daten eingesammelt sind, schau dir an, wie gut jede annotierende Person auf den Gold-Items abgeschnitten hat:
import json
def calculate_gold_accuracy(annotations_file, gold_labels):
with open(annotations_file) as f:
annotations = json.load(f)
annotator_scores = {}
for item_id, item_annotations in annotations.items():
if item_id in gold_labels:
expected = gold_labels[item_id]
for annotator, label in item_annotations.items():
if annotator not in annotator_scores:
annotator_scores[annotator] = {'correct': 0, 'total': 0}
annotator_scores[annotator]['total'] += 1
if label == expected:
annotator_scores[annotator]['correct'] += 1
for annotator, scores in annotator_scores.items():
accuracy = scores['correct'] / scores['total']
print(f"{annotator}: {accuracy:.1%} gold accuracy")
return annotator_scoresZeit als Qualitätsindikator
Potato hält die Bearbeitungszeit in den Ausgabedateien fest. Damit kannst du Annotationen markieren, die womöglich von schlechter Qualität sind:
Zeitdaten auswerten
import json
from statistics import mean, stdev
def analyze_timing(annotations_file):
with open(annotations_file) as f:
data = json.load(f)
times = []
for item in data.values():
if 'time_spent' in item:
times.append(item['time_spent'])
avg_time = mean(times)
std_time = stdev(times)
# Flag annotations that are too fast (< 2 std below mean)
threshold = max(avg_time - 2 * std_time, 2) # At least 2 seconds
flagged = [t for t in times if t < threshold]
print(f"Average time: {avg_time:.1f}s")
print(f"Flagged as too fast: {len(flagged)} items")Qualitätskontrolle auf Plattformebene
Wenn du über eine Crowdsourcing-Plattform arbeitest, nutz deren eigene Qualitätsfunktionen:
Prolific
- Filter zur Vorauswahl einsetzen (Annahmequote, frühere Studien)
- Eine Mindestbearbeitungszeit verlangen
- Aufmerksamkeitsfragen in die vorgeschaltete Umfrage einbauen
- Einreichungen prüfen, bevor du die Bezahlung freigibst
MTurk
- Eine Mindestannahmequote für HITs verlangen (>95 %)
- Qualifikationstests einsetzen
- Automatische Annahme und Ablehnung nach festen Kriterien einrichten
- Arbeitende sperren, die durch die Qualitätsprüfungen fallen
Qualitätsprüfungen in der Nachbearbeitung
Automatisierte Prüfungen auf den eingesammelten Daten:
def quality_check_annotations(annotations_file):
with open(annotations_file) as f:
data = json.load(f)
issues = []
for annotator_id, items in group_by_annotator(data).items():
labels = [item['label'] for item in items]
# Check for single-label bias (always selecting same option)
unique_labels = set(labels)
if len(unique_labels) == 1 and len(labels) > 10:
issues.append(f"{annotator_id}: Only used label '{labels[0]}'")
# Check for position bias (always selecting first option)
# Requires knowing option order in your schema
# Check for very fast submissions
times = [item.get('time_spent', 0) for item in items]
avg_time = sum(times) / len(times) if times else 0
if avg_time < 3:
issues.append(f"{annotator_id}: Average time only {avg_time:.1f}s")
return issuesBewährtes Vorgehen
Führ deine Annotierenden über Potatos Schulungsphase in die Aufgabe ein, bevor echte Annotation beginnt. Schreib klare Richtlinien: unklare Richtlinien erzeugen Uneinigkeit, die nichts mit der Qualität der Annotierenden zu tun hat. Mach einen kleinen Pilotlauf, damit Probleme auffallen, bevor du in die Breite gehst. Kombiniere deine Prüfungen, statt dich auf eine zu verlassen; Aufmerksamkeitstests, Goldstandards und Redundanz greifen jeweils anderes ab. Fang mit großzügigen Schwellen an und zieh sie an, sobald du echte Daten gesehen hast. Gib den Annotierenden Rückmeldung, wo es geht. Beobachte weiter, denn die Qualität rutscht ab, wenn die Leute müde werden. Und halt schriftlich fest, wie du mit Grenzfällen umgehst, damit deine Entscheidungen konsistent bleiben.
Wie du den Einstiegsschritt konkret einrichtest, steht in der Dokumentation zur Schulungsphase.
Zusammenfassung
Qualitätskontrolle für Annotation funktioniert am besten in Schichten:
| Strategie | Umsetzung | Zeitpunkt der Prüfung |
|---|---|---|
| Aufmerksamkeitstests | Surveyflow-Umfragen | während der Annotation |
| Goldstandards | unter die Daten gemischt | nach dem Einsammeln |
| Redundanz | mehrere Annotierende pro Item | nach dem Einsammeln |
| Übereinstimmungsmaße | Python-Skripte | nach dem Einsammeln |
| Zeitanalyse | Zeitstempel der Annotationen | nach dem Einsammeln |
| Plattformfunktionen | Einstellungen in Prolific/MTurk | vor und während des Einsammelns |
Der größte Teil dieser Auswertung passiert im Nachhinein, über Skripte zur Nachbearbeitung. Plane diese Pipeline, bevor du irgendetwas einsammelst, damit du die Felder auch wirklich mitschreibst, die du später brauchst.
Nächste Schritte
- Lies im Detail nach, wie sich die Inter-Annotator-Übereinstimmung berechnen lässt
- Richte die Prolific-Anbindung für Annotation per Crowdsourcing ein
- Konfiguriere Schulungsphasen für den Einstieg neuer Annotierender
Mehr zu Annotationsabläufen in der Dokumentation zu Annotationsschemata.