Best-Worst Scaling
Anotação comparativa eficiente com Best-Worst Scaling no Potato — gera automaticamente tuplas de comparação e converte as seleções em pontuações contínuas de qualidade.
Novo na v2.3.0
Best-Worst Scaling (BWS), também conhecido como Maximum Difference Scaling (MaxDiff), é um método de anotação comparativa em que os anotadores veem uma tupla de itens (normalmente 4) e devem selecionar o item melhor e o pior segundo algum critério. O BWS produz pontuações escalares confiáveis a partir de simples julgamentos binários, exigindo muito menos anotações do que as escalas de avaliação direta para atingir o mesmo poder estatístico.
O BWS é especialmente útil quando:
- As avaliações numéricas diretas sofrem com o viés do anotador (o uso da escala varia entre as pessoas)
- Você precisa de um ranking confiável de centenas ou milhares de itens
- A dimensão de qualidade é inerentemente relativa (por exemplo, "qual tradução é a mais fluente?")
- Você quer maximizar a informação por anotação (cada julgamento de BWS fornece mais bits do que uma avaliação Likert)
Interface de best-worst scaling para anotação comparativa no Potato
Configuração Básica
annotation_schemes:
- annotation_type: best_worst_scaling
name: fluency
description: "Select the BEST and WORST translation by fluency"
# Items to compare
items_key: "translations" # key in instance data containing the list of items
# Tuple size (how many items shown at once)
tuple_size: 4 # typically 4; valid range is 3-8
# Labels for best/worst buttons
best_label: "Most Fluent"
worst_label: "Least Fluent"
# Display options
show_item_labels: true # show "A", "B", "C", "D" labels
randomize_order: true # randomize item order within each tuple
show_source: false # optionally show which system produced each item
# Validation
label_requirement:
required: true # must select both best and worstFormato dos Dados
Cada instância no seu arquivo de dados deve conter uma lista de itens a comparar. O Potato gera tuplas dessa lista automaticamente.
Opção 1: Todos os Itens em Uma Instância
Se você tem um único conjunto de itens para ranquear (por exemplo, traduções de uma frase):
{
"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."}
]
}Opção 2: Tuplas Pré-Geradas
Se você quiser controle total sobre quais itens aparecem juntos, forneça tuplas pré-geradas:
{
"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."}
]
}Geração Automática de Tuplas
Quando sua lista de itens é maior do que o tamanho da tupla, o Potato gera tuplas automaticamente. O algoritmo de geração garante que:
- Todo item apareça em aproximadamente o mesmo número de tuplas
- Todo par de itens coocorra em pelo menos uma tupla (para uma pontuação relativa confiável)
- As tuplas sejam balanceadas, de modo que nenhum item seja sempre mostrado primeiro ou por último
Configure a geração de tuplas:
annotation_schemes:
- annotation_type: best_worst_scaling
name: fluency
items_key: "translations"
tuple_size: 4
tuple_generation:
method: balanced_incomplete # balanced_incomplete or random
tuples_per_item: 5 # each item appears in ~5 tuples
seed: 42 # for reproducibility
ensure_pair_coverage: true # every pair co-occurs at least oncePara um conjunto de N itens com tamanho de tupla T e tuples_per_item = K, o Potato gera aproximadamente N * K / T tuplas no total.
Métodos de Geração
balanced_incomplete (padrão): Usa um delineamento de blocos incompletos balanceados para maximizar a eficiência estatística. Todo item aparece com a mesma frequência, e a coocorrência de pares é a mais uniforme possível. Recomendado para a maioria dos casos de uso.
random: Amostra tuplas aleatoriamente com reposição. Mais rápido para conjuntos de itens muito grandes (N > 10.000), mas estatisticamente menos eficiente. Use quando o balanceamento exato não for crítico.
Pré-Gerando Tuplas via CLI
Para projetos de grande escala, gere as tuplas com antecedência:
python -m potato.bws generate-tuples \
--items data/items.jsonl \
--tuple-size 4 \
--tuples-per-item 5 \
--output data/tuples.jsonl \
--seed 42Métodos de Pontuação
Após a anotação, o Potato calcula as pontuações dos itens a partir dos julgamentos de BWS usando três métodos.
1. Contagem (Padrão)
O método mais simples. A pontuação de cada item é a proporção de vezes que foi selecionado como "melhor" menos a proporção de vezes que foi selecionado como "pior":
Pontuação(item) = (best_count - worst_count) / total_appearances
As pontuações variam de -1,0 (sempre pior) a +1,0 (sempre melhor).
python -m potato.bws score \
--config config.yaml \
--method counting \
--output scores.csv2. Bradley-Terry
Ajusta um modelo de Bradley-Terry às comparações pareadas implícitas nos julgamentos de BWS. Cada seleção de "melhor" implica que o melhor item é preferido a todos os demais itens da tupla; cada seleção de "pior" implica que todos os demais itens são preferidos ao pior.
O Bradley-Terry produz pontuações em escala log-odds com propriedades estatísticas melhores do que a contagem, especialmente com dados esparsos.
python -m potato.bws score \
--config config.yaml \
--method bradley_terry \
--max-iter 1000 \
--tolerance 1e-6 \
--output scores.csv3. Plackett-Luce
Uma generalização do Bradley-Terry que modela o ranking completo implícito em cada julgamento de tupla (melhor > itens intermediários > pior). O Plackett-Luce extrai mais informação de cada anotação do que o Bradley-Terry.
python -m potato.bws score \
--config config.yaml \
--method plackett_luce \
--output scores.csvComparando os Métodos de Pontuação
| Método | Velocidade | Eficiência de Dados | Lida com Dados Esparsos | Modelo Estatístico |
|---|---|---|---|---|
| Contagem | Rápido | Baixa | Sim | Nenhum (descritivo) |
| Bradley-Terry | Médio | Média | Moderado | Comparação pareada |
| Plackett-Luce | Mais lento | Alta | Moderado | Ranking completo |
Para a maioria dos projetos, Bradley-Terry é o melhor padrão. Use Contagem para análise exploratória rápida e Plackett-Luce quando precisar de máxima eficiência estatística a partir de anotações limitadas.
Configuração de Pontuação no YAML
Você também pode configurar a pontuação diretamente na configuração do projeto para cálculo automático:
annotation_schemes:
- annotation_type: best_worst_scaling
name: fluency
items_key: "translations"
tuple_size: 4
scoring:
method: bradley_terry
auto_compute: true # compute scores after each annotation session
output_file: "output/fluency_scores.csv"
include_confidence: true # include confidence intervals
bootstrap_iterations: 1000 # for confidence interval estimationIntegração com o Painel de Administração
O painel de administração inclui uma aba dedicada ao BWS que mostra:
- Distribuição de pontuações: Histograma das pontuações atuais dos itens
- Progresso da anotação: Quantas tuplas foram anotadas em relação ao total
- Cobertura por item: Quantas vezes cada item foi visto
- Consistência entre anotadores: Confiabilidade por divisão pela metade (split-half) das pontuações de BWS
- Convergência das pontuações: Gráfico de linha mostrando como as pontuações se estabilizam à medida que mais anotações são coletadas
Acesse a análise de BWS pela linha de comando:
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
Múltiplas Dimensões de BWS
Você pode executar vários esquemas de BWS sobre o mesmo conjunto de itens para avaliar diferentes dimensões de qualidade:
annotation_schemes:
- annotation_type: best_worst_scaling
name: fluency
description: "Select BEST and WORST by fluency"
items_key: "translations"
tuple_size: 4
best_label: "Most Fluent"
worst_label: "Least Fluent"
- annotation_type: best_worst_scaling
name: adequacy
description: "Select BEST and WORST by meaning preservation"
items_key: "translations"
tuple_size: 4
best_label: "Most Accurate"
worst_label: "Least Accurate"Ambos os esquemas compartilham as mesmas tuplas (o Potato gera um conjunto de tuplas por items_key), então os anotadores veem cada tupla uma vez, mas fornecem dois julgamentos.
Formato de Saída
As anotações de BWS são salvas por tupla:
{
"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"
}Exemplo Completo
Configuração completa para avaliar sistemas de tradução automática:
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: best_worst_scaling
name: overall_quality
description: "Select the BEST and WORST translation"
items_key: "translations"
tuple_size: 4
best_label: "Best Translation"
worst_label: "Worst Translation"
randomize_order: true
show_item_labels: true
tuple_generation:
method: balanced_incomplete
tuples_per_item: 5
seed: 42
scoring:
method: bradley_terry
auto_compute: true
output_file: "output/quality_scores.csv"
include_confidence: true
output_annotation_dir: "output/"
export_annotation_format: "jsonl"Leitura Adicional
- Comparação Pareada -- comparação mais simples de dois itens
- Escalas Likert -- alternativa de avaliação direta
- Multirate -- avaliações diretas multidimensionais
- Formatos de Exportação -- exporte dados de BWS para análise
Para detalhes de implementação, consulte a documentação de origem.