Skip to content

最優-最差量表(Best-Worst Scaling)

在 Potato 中執行最優-最差量表:標註者在每個元組裡選出最好和最差的項目,再由計數法、Bradley-Terry 或 Plackett-Luce 換算成分數。

v2.3.0 新增

Best-Worst Scaling(BWS),也叫 MaxDiff,把一組項目(通常是四個)擺在標註者面前,請他按某個標準選出最好的和最差的。每個元組點兩下,得到的資訊比打一次分更多;而且因為判斷是比較式的,它繞開了"一個標註者的 7 分相當於另一個標註者的 5 分"這個麻煩。

以下情況值得為 BWS 做這套配置:

  • 直接打數值分會受到標註者之間量表使用習慣差異的影響
  • 你需要在成百上千個項目上得到一份可靠的排名
  • 品質維度本身就是相對的,比如哪個譯文讀起來最流暢

Best-worst scaling annotation interfaceBest-worst scaling interface for comparative annotation in Potato

配置

一個 BWS 任務分成兩部分。方案規定問標註者什麼,頂層的 bws_config 塊規定元組怎麼生成、怎麼評分。

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

方案只接受 tuple_size、best_description、worst_description、sequential_key_binding 和 label_requirement,此外沒有別的。凡是和生成元組或給元組評分有關的,都寫在 bws_config 裡。

缺了 bws_config 塊的 bws 方案,會在一個空的項目列表上渲染問題——BWS 任務開啟是一片空白,通常就是這個原因。

bws_config 選項

選項說明
tuple_size一個元組裡同時顯示多少個項目
num_tuples總共生成多少個元組
min_item_appearances每個項目至少要出現在多少個元組裡
seed固定取樣,使一次執行可以復現
scoring.methodcounting、bradley_terry 或 plackett_luce

調高 min_item_appearances 會收緊每個項目的分數,代價是更多的比較次數。分數出來噪聲大的時候,擰的就是這個旋鈕。

資料格式

資料檔案的每一行是一個項目,Potato 從這個池子裡取樣出元組。

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

元組生成會讓整個設計保持平衡:每個項目出現的次數大致相同,需要相互比較的配對共同出現得足夠頻繁,分數才有可比性。設了 seed,這套分配就可以復現。

評分

評分在收集完成之後進行,從命令列執行:

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

結果寫到輸出目錄下的 bws_scores.tsv,除非 --output 指定了別的路徑。參數一共三個:--config、--method 和 --output。

計數法

預設方法,也是最透明的一個。一個項目的分數,是它被選為最好的比例減去被選為最差的比例,所以分數落在 -1.0 到 +1.0 之間。它不需要額外依賴;如果你希望讀者能自己手算一遍來核對,報這個方法。

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

Bradley-Terry

在每個元組隱含的成對比較上擬合一個模型:最好的項目勝過元組裡其餘所有項目,其餘所有項目又都勝過最差的那個。資料稀疏時,它比計數法處理得更好。

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

Plackett-Luce

把每次判斷看作兩次選擇:先從整個元組中選出最好的,再從剩下的項目中選出最差的,這正是 MaxDiff 對最優-最差判斷如何做出的建模。它用最大似然為每個項目擬合一個效用值。2.10.2 之前,它擬合的是與 Bradley-Terry 相同的成對比較,返回的分數完全相同;如果你報告過它的結果,請用 2.10.2 或更高版本重新計算分數。

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

選擇方法

方法速度使用的資訊適用場景
counting快最好和最差的計數探索性分析,以及希望別人容易核對的結果
bradley_terry中等隱含的成對比較通常的預設選擇
plackett_luce較慢每一次最好和最差的選擇,按做出的先後順序對判斷本身的似然模型

bradley_terry 需要 pip install choix。plackett_luce 用的是 scipy,Potato 已經自帶安裝。

一次評多個維度

在同一批項目上放兩個 BWS 方案,每個元組就收集兩次判斷,代價是多點一對按鈕,而不是把語料再跑一遍:

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"

輸出裡有什麼

每個方案記錄下被選為最好的項目和被選為最差的項目:

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

分數不在這個檔案裡。它們是事後由 potato.bws_scoring 算出來的——正因為如此,你可以換一種方法給一項已經做完的研究重新評分,而不必重新收集任何資料。

監控

管理面板有一個 BWS 標籤頁,顯示標註進度和當前的項目分數,這樣你可以在決定停止收集之前,先看看排名有沒有穩定下來。

完整示例

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

先收集標註,再給它們評分:

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

延伸閱讀

有關實現細節,請參閱源文件。