Skip to content

Échelle best-worst

Annotation comparative efficace avec l'échelle best-worst dans Potato — génération automatique des tuples de comparaison et conversion des choix en scores de qualité continus.

Nouveau en v2.3.0

L'échelle best-worst (BWS), aussi appelée MaxDiff, présente à l'annotateur un tuple d'éléments, en général quatre, et lui demande de désigner le meilleur et le pire selon un critère donné. Deux clics par tuple apportent plus d'information qu'une note, et comme le jugement est comparatif, il évite le problème du 7 d'un annotateur qui vaut le 5 d'un autre.

La BWS vaut la peine d'être mise en place quand :

  • Les notes numériques directes souffrent de différences d'usage de l'échelle entre annotateurs
  • Vous avez besoin d'un classement fiable sur des centaines ou des milliers d'éléments
  • La dimension de qualité est relative par nature, par exemple savoir quelle traduction se lit le plus facilement

Interface d'annotation en échelle best-worstInterface d'échelle best-worst pour l'annotation comparative dans Potato

Configuration

Une tâche BWS comporte deux parties. Le schéma définit ce que l'on demande à l'annotateur, et le bloc bws_config de premier niveau définit comment les tuples sont construits et notés.

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

Le schéma accepte tuple_size, best_description, worst_description, sequential_key_binding et label_requirement, et rien d'autre. Tout ce qui concerne la génération ou le score des tuples va dans bws_config.

Un schéma bws sans bloc bws_config affiche une question sur une liste d'éléments vide. C'est la raison habituelle pour laquelle une tâche BWS s'affiche vide.

Options de bws_config

OptionDescription
tuple_sizeNombre d'éléments présentés dans un tuple
num_tuplesNombre total de tuples à générer
min_item_appearancesNombre minimal de tuples dans lesquels chaque élément apparaît
seedFixe l'échantillonnage, pour qu'une exécution puisse être reproduite
scoring.methodcounting, bradley_terry ou plackett_luce

Augmenter min_item_appearances rend le score de chaque élément plus précis, au prix de comparaisons supplémentaires. C'est le réglage à modifier quand les scores sont bruités.

Format des données

Chaque ligne du fichier de données est un élément, et Potato tire les tuples de cet ensemble.

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."}

La génération des tuples équilibre le plan : chaque élément apparaît à peu près aussi souvent que les autres, et les paires à comparer se retrouvent ensemble assez souvent pour que les scores soient comparables. Définir seed rend cette affectation reproductible.

Calcul des scores

Le calcul des scores se fait après la collecte, en ligne de commande :

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

Le résultat est écrit dans bws_scores.tsv, dans le répertoire de sortie, sauf si --output indique un autre chemin. Les trois options sont --config, --method et --output.

Comptage

La méthode par défaut, et la plus transparente. Le score d'un élément est la proportion de fois où il a été choisi comme meilleur moins la proportion de fois où il a été choisi comme pire, si bien que les scores vont de -1,0 à +1,0. Elle ne demande aucune dépendance supplémentaire, et c'est la méthode à publier quand vous voulez qu'un lecteur puisse refaire le calcul à la main.

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

Bradley-Terry

Ajuste un modèle sur les comparaisons par paires qu'implique chaque tuple : le meilleur élément l'emporte sur tous les autres éléments de son tuple, et tous les autres l'emportent sur le pire. Cette méthode gère mieux les données éparses que le comptage.

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

Plackett-Luce

Traite chaque jugement comme deux choix : le meilleur dans le tuple entier, puis le pire parmi les éléments restants. C'est le modèle MaxDiff de la façon dont se forment les jugements best-worst. Il ajuste une utilité par élément par maximum de vraisemblance. Avant la 2.10.2, il ajustait les mêmes paires que Bradley-Terry et renvoyait des scores identiques : si vous avez publié ses résultats, recalculez les scores avec la 2.10.2 ou une version ultérieure.

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

Choisir une méthode

MéthodeVitesseInformation utiliséeIdéale pour
countingRapideNombre de choix comme meilleur et comme pireL'analyse exploratoire, et les résultats que vous voulez faciles à vérifier
bradley_terryMoyenneComparaisons par paires implicitesLe choix par défaut habituel
plackett_lucePlus lenteChaque choix du meilleur et du pire, dans l'ordre où il est faitUn modèle de vraisemblance du jugement lui-même

bradley_terry nécessite pip install choix. plackett_luce utilise scipy, que Potato installe déjà.

Plusieurs dimensions à la fois

Deux schémas BWS sur les mêmes éléments recueillent deux jugements par tuple, ce qui coûte une paire de clics de plus au lieu d'un second passage sur le corpus :

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"

Contenu de la sortie

Chaque schéma enregistre l'élément choisi comme meilleur et l'élément choisi comme pire :

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

Les scores ne figurent pas dans ce fichier. Ils sont calculés ensuite par potato.bws_scoring, ce qui permet de recalculer les scores d'une étude terminée avec une autre méthode sans rien recollecter.

Suivi

Le tableau de bord d'administration comporte un onglet BWS qui affiche l'avancement de l'annotation et les scores actuels des éléments. Vous pouvez ainsi vérifier que le classement s'est stabilisé avant de décider d'arrêter la collecte.

Exemple complet

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

Collectez les annotations, puis calculez les scores :

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

Pour aller plus loin

Pour les détails d'implémentation, voir la documentation source.