É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 Maximum Difference Scaling (MaxDiff), est une méthode d'annotation comparative où l'on montre aux annotateurs un tuple d'éléments (typiquement 4) en leur demandant de choisir le meilleur et le pire selon un critère donné. La BWS produit des scores scalaires fiables à partir de jugements binaires simples, et exige bien moins d'annotations que les échelles de notation directe pour atteindre la même puissance statistique.
La BWS est particulièrement utile quand :
- Les notations numériques directes souffrent d'un biais d'annotateur (l'usage de l'échelle varie d'une personne à l'autre)
- Vous avez besoin d'un classement fiable de centaines ou de milliers d'éléments
- La dimension de qualité est relative par nature (par exemple, « quelle traduction est la plus fluide ? »)
- Vous voulez maximiser l'information par annotation (chaque jugement BWS apporte plus de bits qu'une note de Likert)
Interface d'échelle best-worst pour l'annotation comparative dans Potato
Configuration de base
annotation_schemes:
- annotation_type: bws
name: fluency
description: "Select the BEST and WORST translation by fluency"
# Items to compare
# Tuple size (how many items shown at once)
tuple_size: 4 # typically 4; valid range is 3-8
# Labels for best/worst buttons
best_description: "Most Fluent"
worst_description: "Least Fluent"
# Display options
# Validation
label_requirement:
required: true # must select both best and worstFormat des données
Chaque instance de votre fichier de données doit contenir une liste d'éléments à comparer. Potato en génère les tuples automatiquement.
Option 1 : tous les éléments dans une instance
Si vous avez un seul ensemble d'éléments à classer (par exemple les traductions d'une même phrase) :
{
"id": "sent_001",
"source": "The cat sat on the mat.",
"translations": [
{"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."}
]
}Option 2 : tuples pré-générés
Si vous voulez maîtriser entièrement quels éléments apparaissent ensemble, fournissez des tuples pré-générés :
{
"id": "tuple_001",
"translations": [
{"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."}
]
}Génération automatique des tuples
Quand votre liste d'éléments dépasse la taille du tuple, Potato génère les tuples automatiquement. L'algorithme de génération garantit que :
- Chaque élément apparaît dans à peu près le même nombre de tuples
- Chaque paire d'éléments se retrouve ensemble dans au moins un tuple (pour un score relatif fiable)
- Les tuples sont équilibrés de sorte qu'aucun élément ne soit toujours affiché en premier ou en dernier
Configurez la génération de tuples :
annotation_schemes:
- annotation_type: bws
name: fluency
tuple_size: 4Pour un ensemble de N éléments avec une taille de tuple T et tuples_per_item = K, Potato génère environ N * K / T tuples au total.
Méthodes de génération
balanced_incomplete (par défaut) : utilise un plan en blocs incomplets équilibrés pour maximiser l'efficacité statistique. Chaque élément apparaît aussi souvent que les autres, et la co-occurrence des paires est aussi uniforme que possible. Recommandé dans la plupart des cas.
random : échantillonne les tuples au hasard avec remise. Plus rapide pour de très grands ensembles d'éléments (N > 10 000) mais statistiquement moins efficace. À utiliser quand l'équilibre exact n'est pas critique.
Pré-générer les tuples en ligne de commande
Pour des projets à grande échelle, générez les tuples à l'avance :
python -m potato.bws generate-tuples \
--items data/items.jsonl \
--tuple-size 4 \
--tuples-per-item 5 \
--output data/tuples.jsonl \
--seed 42Méthodes de calcul des scores
Après l'annotation, Potato calcule les scores des éléments à partir des jugements BWS selon trois méthodes.
1. Comptage (par défaut)
La méthode la plus simple. 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 » :
Score(item) = (best_count - worst_count) / total_appearances
Les scores vont de -1,0 (toujours le pire) à +1,0 (toujours le meilleur).
python -m potato.bws score \
--config config.yaml \
--method counting \
--output scores.csv2. Bradley-Terry
Ajuste un modèle de Bradley-Terry aux comparaisons par paires impliquées par les jugements BWS. Chaque choix de « meilleur » implique que cet élément est préféré à tous les autres du tuple ; chaque choix de « pire » implique que tous les autres lui sont préférés.
Bradley-Terry produit des scores sur une échelle de log-cotes, aux propriétés statistiques meilleures que le comptage, en particulier avec des données éparses.
python -m potato.bws score \
--config config.yaml \
--method bradley_terry \
--max-iter 1000 \
--tolerance 1e-6 \
--output scores.csv3. Plackett-Luce
Une généralisation de Bradley-Terry qui modélise le classement complet impliqué par chaque jugement de tuple (meilleur > éléments intermédiaires > pire). Plackett-Luce extrait plus d'information de chaque annotation que Bradley-Terry.
python -m potato.bws score \
--config config.yaml \
--method plackett_luce \
--output scores.csvComparaison des méthodes de score
| Méthode | Vitesse | Efficacité en données | Gère les données éparses | Modèle statistique |
|---|---|---|---|---|
| Comptage | Rapide | Faible | Oui | Aucun (descriptif) |
| Bradley-Terry | Moyenne | Moyenne | Modérément | Comparaison par paires |
| Plackett-Luce | Plus lente | Élevée | Modérément | Classement complet |
Pour la plupart des projets, Bradley-Terry est le meilleur choix par défaut. Prenez le comptage pour une analyse exploratoire rapide et Plackett-Luce quand il faut tirer le maximum d'efficacité statistique d'annotations limitées.
Configuration du score en YAML
Vous pouvez aussi configurer le calcul des scores directement dans la configuration du projet, pour un calcul automatique :
annotation_schemes:
- annotation_type: bws
name: fluency
tuple_size: 4Intégration au tableau de bord d'administration
Le tableau de bord d'administration comporte un onglet BWS dédié qui affiche :
- Distribution des scores : histogramme des scores actuels des éléments
- Avancement de l'annotation : combien de tuples ont été annotés sur le total
- Couverture par élément : combien de fois chaque élément a été vu
- Cohérence inter-annotateurs : fidélité par bissection des scores BWS
- Convergence des scores : courbe montrant comment les scores se stabilisent à mesure que les annotations s'accumulent
Consultez les analyses BWS en ligne de commande :
python -m potato.bws stats --config config.yamlBWS Statistics
==============
Schema: fluency
Items: 200
Tuples: 250 (annotated: 180 / 250)
Annotations: 540 (3 annotators)
Score Summary (Bradley-Terry):
Mean: 0.02
Std: 0.43
Range: -0.91 to +0.87
Top 5 Items:
sys_d: 0.87 (±0.08)
sys_a: 0.72 (±0.09)
sys_f: 0.65 (±0.10)
sys_b: 0.51 (±0.11)
sys_k: 0.48 (±0.09)
Split-Half Reliability: r = 0.94
Plusieurs dimensions BWS
Vous pouvez faire tourner plusieurs schémas BWS sur le même ensemble d'éléments pour évaluer différentes dimensions de qualité :
annotation_schemes:
- annotation_type: bws
name: fluency
description: "Select BEST and WORST by fluency"
tuple_size: 4
best_description: "Most Fluent"
worst_description: "Least Fluent"
- annotation_type: bws
name: adequacy
description: "Select BEST and WORST by meaning preservation"
tuple_size: 4
best_description: "Most Accurate"
worst_description: "Least Accurate"Les deux schémas partagent les mêmes tuples (Potato génère un jeu de tuples par items_key) : les annotateurs voient chaque tuple une fois mais rendent deux jugements.
Format de sortie
Les annotations BWS sont enregistrées par tuple :
{
"id": "tuple_001",
"annotations": {
"fluency": {
"best": "sys_d",
"worst": "sys_c"
},
"adequacy": {
"best": "sys_a",
"worst": "sys_c"
}
},
"annotator": "user_1",
"timestamp": "2026-03-01T14:22:00Z"
}Exemple complet
Configuration complète pour évaluer des systèmes de traduction automatique :
annotation_task_name: "MT System Ranking (BWS)"
task_dir: "."
data_files:
- "data/mt_tuples.jsonl"
item_properties:
id_key: id
text_key: source
instance_display:
fields:
- key: source
type: text
display_options:
label: "Source Sentence"
annotation_schemes:
- annotation_type: bws
name: overall_quality
description: "Select the BEST and WORST translation"
tuple_size: 4
best_description: "Best Translation"
worst_description: "Worst Translation"
output_annotation_dir: "output/"
export_annotation_format: "jsonl"Pour aller plus loin
- Comparaison par paires -- comparaison plus simple entre deux éléments
- Échelles de Likert -- alternative en notation directe
- Multirate -- notations directes multidimensionnelles
- Formats d'export -- exportez les données BWS pour analyse
Pour les détails d'implémentation, voir la documentation source.