Skip to content

Best-Worst Scaling

使用 Best-Worst Scaling 進行高效的比較式標註,支援自動元組生成和評分。

v2.3.0 新增

Best-Worst Scaling(BWS),也稱為最大差異縮放(MaxDiff),是一種比較式標註方法。標註人員看到一組項目(通常 4 個),根據某個標準選擇最好最差的項目。BWS 從簡單的二元判斷中生成可靠的標量分數,在達到相同統計效力時所需的標註量遠少於直接評分量表。

BWS 特別適用於以下場景:

  • 直接數值評分受標註者偏差影響(不同人的量表使用習慣不同)
  • 你需要對數百或數千個項目進行可靠排名
  • 品質維度本質上是相對的(例如,"哪個翻譯最流暢?")
  • 你希望最大化每次標註的資訊量(每次 BWS 判斷比 Likert 評分提供更多資訊位)

基本配置

yaml
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 worst

資料格式

資料檔案中的每個實例應包含一個待比較的項目列表。Potato 自動從此列表生成元組。

選項 1:所有項目在一個實例中

如果你有一組需要排名的項目(例如,一個句子的多個翻譯):

json
{
  "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."}
  ]
}

選項 2:預生成的元組

如果你想完全控制哪些項目同時出現,可以提供預生成的元組:

json
{
  "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."}
  ]
}

自動元組生成

當項目列表長度超過元組大小時,Potato 自動生成元組。生成演算法確保:

  • 每個項目出現在大致相同數量的元組中
  • 每對項目至少在一個元組中共同出現(用於可靠的相對評分)
  • 元組是平衡的,沒有項目總是排在第一或最後

配置元組生成:

yaml
annotation_schemes:
  - annotation_type: bws
    name: fluency
    tuple_size: 4

對於包含 N 個項目、元組大小為 T、tuples_per_item = K 的集合,Potato 大約生成 N * K / T 個元組。

生成方法

balanced_incomplete(預設):使用平衡不完全區組設計來最大化統計效率。每個項目出現頻率相等,配對共現儘可能均勻。推薦用於大多數場景。

random:有放回地隨機取樣元組。對於非常大的項目集(N > 10,000)更快,但統計效率較低。當精確平衡不重要時使用。

通過 CLI 預生成元組

對於大規模項目,提前生成元組:

bash
python -m potato.bws generate-tuples \
  --items data/items.jsonl \
  --tuple-size 4 \
  --tuples-per-item 5 \
  --output data/tuples.jsonl \
  --seed 42

評分方法

標註完成後,Potato 使用三種方法從 BWS 判斷中計算項目分數。

1. 計數法(預設)

最簡單的方法。每個項目的分數是被選為"最好"的比例減去被選為"最差"的比例:

Score(item) = (best_count - worst_count) / total_appearances

分數範圍從 -1.0(總是最差)到 +1.0(總是最好)。

bash
python -m potato.bws score \
  --config config.yaml \
  --method counting \
  --output scores.csv

2. Bradley-Terry

將 Bradley-Terry 模型擬合到 BWS 判斷所隱含的成對比較中。每次"最好"選擇意味著該項目優於元組中的所有其他項目;每次"最差"選擇意味著所有其他項目優於最差項目。

Bradley-Terry 在對數機率尺度上產生分數,具有比計數法更好的統計性質,尤其是在資料稀疏時。

bash
python -m potato.bws score \
  --config config.yaml \
  --method bradley_terry \
  --max-iter 1000 \
  --tolerance 1e-6 \
  --output scores.csv

3. Plackett-Luce

Bradley-Terry 的推廣,對每個元組判斷所隱含的完整排名進行建模(最好 > 中間項目 > 最差)。Plackett-Luce 從每次標註中提取比 Bradley-Terry 更多的資訊。

bash
python -m potato.bws score \
  --config config.yaml \
  --method plackett_luce \
  --output scores.csv

評分方法比較

方法速度資料效率處理稀疏資料統計模型
計數法無(描述性)
Bradley-Terry中等中等中等成對比較
Plackett-Luce較慢中等完整排名

對於大多數項目,Bradley-Terry 是最佳預設選擇。使用計數法進行快速探索性分析,使用 Plackett-Luce 當你需要從有限標註中獲得最大統計效率。

YAML 中的評分配置

你也可以直接在項目配置中配置評分以實現自動計算:

yaml
annotation_schemes:
  - annotation_type: bws
    name: fluency
    tuple_size: 4

管理面板整合

管理面板包含一個專用的 BWS 標籤頁,顯示:

  • 分數分佈:當前項目分數的直方圖
  • 標註進度:已標註元組數與總數
  • 每項覆蓋率:每個項目被檢視的次數
  • 標註者間一致性:BWS 分數的分半信度
  • 分數收斂:折線圖顯示隨著更多標註收集分數如何趨於穩定

通過命令列訪問 BWS 分析:

bash
python -m potato.bws stats --config config.yaml
text
BWS 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

多維度 BWS

你可以在同一組項目上執行多個 BWS 方案來評估不同的品質維度:

yaml
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"

兩個方案共享相同的元組(Potato 為每個 items_key 生成一組元組),因此標註人員看到每個元組一次但提供兩個判斷。

輸出格式

BWS 標註按元組儲存:

json
{
  "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"
}

完整示例

用於評估機器翻譯系統的完整配置:

yaml
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/"
output_annotation_format: "jsonl"

延伸閱讀

有關實現詳情,請參閱源文件