Skip to content

Best-Worst Scaling

Best-Worst Scaling in Potato. Annotatoren wählen in jedem Tupel das beste und das schlechteste Element, und Zählung, Bradley-Terry oder Plackett-Luce berechnet daraus Scores.

Neu in v2.3.0

Best-Worst Scaling (BWS), auch MaxDiff genannt, zeigt Annotatoren ein Tupel aus Elementen, meist vier, und fragt nach dem besten und dem schlechtesten Element gemäß einem Kriterium. Zwei Klicks pro Tupel liefern mehr Information als eine Bewertung, und weil das Urteil vergleichend ist, umgeht es das Problem, dass die 7 des einen Annotators die 5 eines anderen ist.

BWS lohnt den Einrichtungsaufwand, wenn:

  • Direkte numerische Bewertungen darunter leiden, dass Annotatoren die Skala unterschiedlich nutzen
  • Sie eine zuverlässige Rangfolge über Hunderte oder Tausende von Elementen brauchen
  • Die Qualitätsdimension von Natur aus relativ ist, etwa welche Übersetzung sich am flüssigsten liest

Annotationsoberfläche für Best-Worst ScalingBest-Worst-Scaling-Oberfläche für vergleichende Annotation in Potato

Konfiguration

Eine BWS-Aufgabe besteht aus zwei Teilen. Das Schema legt fest, was die Annotatoren gefragt werden, und der Top-Level-Block bws_config legt fest, wie Tupel gebildet und bewertet werden.

yaml
bws_config:
  tuple_size: 4              # items shown at once
  min_item_appearances: 8    # how often each item must appear across tuples
  seed: 42
  scoring:
    method: counting         # counting | bradley_terry | plackett_luce
 
annotation_schemes:
  - annotation_type: bws
    name: fluency
    description: "Select the BEST and WORST translation by fluency"
    tuple_size: 4
    best_description: "Most Fluent"
    worst_description: "Least Fluent"
    sequential_key_binding: true
    label_requirement:
      required: true

Das Schema nimmt tuple_size, best_description, worst_description, sequential_key_binding und label_requirement an, sonst nichts. Alles, was das Erzeugen oder Bewerten von Tupeln betrifft, gehört in bws_config.

Ein bws-Schema ohne bws_config-Block zeigt eine Frage über einer leeren Elementliste an. Das ist der übliche Grund, warum eine BWS-Aufgabe leer erscheint.

Optionen von bws_config

OptionBeschreibung
tuple_sizeWie viele Elemente in einem Tupel erscheinen
num_tuplesWie viele Tupel insgesamt erzeugt werden
min_item_appearancesDie Mindestzahl an Tupeln, in denen jedes Element vorkommt
seedLegt die Stichprobenziehung fest, sodass sich ein Lauf reproduzieren lässt
scoring.methodcounting, bradley_terry oder plackett_luce

Ein höherer Wert für min_item_appearances macht den Score jedes Elements genauer, kostet aber mehr Vergleiche. An diesem Regler drehen Sie, wenn die Scores verrauscht ausfallen.

Datenformat

Jede Zeile der Datendatei ist ein Element, und Potato zieht Tupel aus diesem Pool.

json
{"id": "sys_a", "text": "Le chat s'est assis sur le tapis."}
{"id": "sys_b", "text": "Le chat a assis sur le tapis."}
{"id": "sys_c", "text": "Le chat etait assis sur le mat."}
{"id": "sys_d", "text": "Le chat se tenait sur le tapis."}

Die Tupelgenerierung sorgt für ein ausgewogenes Design. Jedes Element erscheint etwa gleich oft, und die Paare, die verglichen werden müssen, treten oft genug gemeinsam auf, damit die Scores vergleichbar sind. Mit seed wird diese Zuordnung reproduzierbar.

Bewertung

Die Bewertung läuft nach der Datenerhebung über die Kommandozeile:

bash
python -m potato.bws_scoring --config config.yaml --method counting

Das Ergebnis wird in bws_scores.tsv im Ausgabeverzeichnis geschrieben, sofern --output keinen anderen Pfad angibt. Die drei Flags sind --config, --method und --output.

Zählung

Die Standardmethode und die transparenteste. Der Score eines Elements ist der Anteil der Male, in denen es als bestes gewählt wurde, minus den Anteil der Male, in denen es als schlechtestes gewählt wurde, sodass die Scores von -1,0 bis +1,0 reichen. Sie braucht keine zusätzlichen Abhängigkeiten und ist die Methode, die Sie angeben sollten, wenn Leser das Ergebnis von Hand nachrechnen können sollen.

bash
python -m potato.bws_scoring --config config.yaml --method counting --output scores.tsv

Bradley-Terry

Passt ein Modell an die paarweisen Vergleiche an, die jedes Tupel impliziert. Das beste Element schlägt jedes andere Element seines Tupels, und jedes andere Element schlägt das schlechteste. Mit spärlichen Daten kommt die Methode besser zurecht als die Zählung.

bash
python -m potato.bws_scoring --config config.yaml --method bradley_terry

Plackett-Luce

Modelliert die vollständige Rangfolge, die jedes Urteil impliziert (das beste Element über den mittleren, die mittleren über dem schlechtesten), und holt so aus jeder Annotation mehr heraus als Bradley-Terry.

bash
python -m potato.bws_scoring --config config.yaml --method plackett_luce

Wahl der Methode

MethodeGeschwindigkeitGenutzte InformationAm besten für
countingSchnellAnzahl der Best- und Worst-WahlenExplorative Analysen und Ergebnisse, die leicht nachprüfbar sein sollen
bradley_terryMittelImplizierte paarweise VergleicheDie übliche Standardwahl
plackett_luceLangsamerDie vollständige implizierte RangfolgeDas Maximum aus wenigen Annotationen herausholen

bradley_terry und plackett_luce passen Modelle an, statt zu zählen, und brauchen daher pip install choix.

Mehrere Dimensionen gleichzeitig

Zwei BWS-Schemata über denselben Elementen erfassen zwei Urteile pro Tupel. Das kostet ein zusätzliches Klickpaar statt eines zweiten Durchgangs durch das Korpus:

yaml
annotation_schemes:
  - annotation_type: bws
    name: fluency
    description: "Select the BEST and WORST by fluency"
    tuple_size: 4
    best_description: "Most Fluent"
    worst_description: "Least Fluent"
 
  - annotation_type: bws
    name: adequacy
    description: "Select the BEST and WORST by meaning preservation"
    tuple_size: 4
    best_description: "Most Accurate"
    worst_description: "Least Accurate"

Was die Ausgabe enthält

Jedes Schema speichert das als bestes und das als schlechtestes gewählte Element:

json
{
  "fluency": {"best": "sys_d", "worst": "sys_c"},
  "adequacy": {"best": "sys_a", "worst": "sys_c"}
}

Die Scores stehen nicht in dieser Datei. Sie werden nachträglich von potato.bws_scoring berechnet, und deshalb können Sie eine abgeschlossene Studie mit einer anderen Methode neu bewerten, ohne neue Daten zu erheben.

Überwachung

Das Admin-Dashboard hat einen BWS-Tab, der den Annotationsfortschritt und die aktuellen Element-Scores zeigt. So sehen Sie, ob sich die Rangfolge stabilisiert hat, bevor Sie die Erhebung beenden.

Vollständiges Beispiel

yaml
annotation_task_name: "MT System Ranking (BWS)"
task_dir: "."
 
data_files:
  - "data/mt_systems.jsonl"
 
item_properties:
  id_key: id
  text_key: text
 
bws_config:
  tuple_size: 4
  min_item_appearances: 8
  seed: 42
  scoring:
    method: bradley_terry
 
annotation_schemes:
  - annotation_type: bws
    name: overall_quality
    description: "Select the BEST and the WORST translation"
    tuple_size: 4
    best_description: "Best Translation"
    worst_description: "Worst Translation"
    sequential_key_binding: true
    label_requirement:
      required: true
 
output_annotation_dir: "annotation_output/"
export_annotation_format: jsonl
 
user_config:
  allow_all_users: true

Erheben Sie die Annotationen und bewerten Sie sie anschließend:

bash
potato start config.yaml -p 8000
python -m potato.bws_scoring --config config.yaml --method bradley_terry

Weiterführende Lektüre

Implementierungsdetails finden Sie in der Quelldokumentation.