眾包投票、點標記與邊界框的共識聚合
把多名標註者對每個條目的答案合併為一個共識,給出投票佔比、DBSCAN 點聚類和中位數邊界框,做法與 Zooniverse 的 reducer 一致。
v2.13.0 新增
consensus 匯出把多名標註者對每個條目的答案合併為每個條目一個共識答案,做法與 Zooniverse 等公民科學項目合併志願者分類結果的方式相同。在志願者項目中,每個物件(subject)會分發給多名志願者,例如數一張群落照片中的企鵝,或標出一幀紅外相機影像中的動物。對於選擇題,匯出報告每個答案有多少名標註者選擇,並把每個條目標記為 retired 或 needs_review。對於點標記,匯出把標註者的點聚類為每個目標一個點;對於邊界框,匯出為每個目標報告一箇中位數框。公民科學以外的眾包團隊也用同一個匯出把每個條目上的多個標籤合併為一個標籤。沿用 Zooniverse 的說法,Potato 把在某個條目上回答了某個問題的標註者稱為該條目的分類者(classifier)。
- 選擇題:
radio、select、likert和multiselect方案會得到每個答案的人數和佔比、得票最多的答案、平票情況以及狀態。 - 數值題:
slider和number方案會得到人數、均值、中位數、標準差、最小值和最大值。 - 點:
image_annotation方案中的landmark標記用 DBSCAN 聚類,半徑以畫素為單位,或以影像尺寸的比例為單位。 - 框:
image_annotation方案中的bbox標記按重疊程度分組,每組得到一箇中位數框。 - 安裝: 這個匯出只需要 Potato 本身。聚類用到 numpy,而 numpy 是 Potato 的核心依賴,會隨 Potato 一起安裝。
共識與一致性
Potato 衡量標註者之間的一致程度,而共識匯出為每個條目給出一個答案。reliability 匯出和 /admin/iaa 頁面會針對整個研究中的每個問題報告 Krippendorff's alpha,alpha 偏低的團隊首先應檢查標註指南或標註者培訓。共識匯出逐條目工作。每個條目都有一個狀態,記錄該條目上的標註者是否足夠一致,可以保留這個答案。依賴共識之前先檢查一致性,因為共識匯出不論標註者的準確率如何,都給每名標註者一票。關於空間標籤上經過機遇校正的一致性,參見如何測量邊界框上的標註者間一致性。
MACE 對每名標註者的投票加權,而不是把每一票同等計數。MACE 在 radio、likert、select 和 multiselect 方案上為每名標註者估計一個能力分數,並根據加權後的投票為每個條目推斷一個標籤。聚合眾包標籤討論了能力模型何時優於不加權投票,以及何時應保留答案的分佈。MACE 不讀取點標記或框標記。對於影像上的標記,請使用共識匯出。
配置
下面的配置搭建一個企鵝計數工作流,包含一個三選一問題、一個多選問題,以及一個影像方案;在影像方案中,標註者用點標出每隻成年企鵝,並在每個巢周圍畫一個框:
annotation_task_name: "Penguin colony counts"
task_dir: .
data_files: [data/colonies.jsonl]
item_properties: {id_key: id, text_key: image}
output_annotation_dir: annotation_output
num_annotators_per_item: 5
user_config:
allow_all_users: true
annotation_schemes:
- annotation_type: radio
name: T0
description: "Are there penguins in the image?"
labels: ["Yes", "No", "Unsure"]
- annotation_type: multiselect
name: T1
description: "What else is in the image?"
labels: [Ice, Water, Rock]
- annotation_type: image_annotation
name: T2
description: "Mark each adult penguin and draw a box round each nest"
source_field: image
tools: [landmark, bbox]
labels:
- {name: Adult, color: "#00ff00"}
- {name: Nest, color: "#ff0000"}
consensus_aggregation:
agreement_threshold: 0.8
min_classifiers: 2
points:
eps: 10
eps_unit: pixels
min_samples: 2
boxes:
iou_threshold: 0.5方案名 T0、T1 和 T2 是 Zooniverse 的任務 ID。項目從 Zooniverse 匯入時,potato import 會把任務 ID 保留為方案名;在 Potato 中搭建的研究可以使用任意名稱。Potato 把每張影像分發給五名標註者(num_annotators_per_item: 5)。在 agreement_threshold: 0.8 下,五名標註者中須有四名給出相同答案,條目才會退役。在 min_classifiers: 2 下,單個標註者的答案永遠不算共識。彼此相距 10 畫素以內的兩個點可以形成一個簇;兩個框只有在交併比(IoU)至少為 0.5 時才算同一個巢。
要以畫素半徑聚類,匯出需要知道每張影像的尺寸。每個條目給出影像,以及影像以畫素計的寬和高:
{"id": "9001", "image": "/media/colony_9001.png", "image_width": 1000, "image_height": 500}這個塊中的每個鍵都是可選的:
| 鍵 | 預設值 | --option 名稱 | 含義 |
|---|---|---|---|
agreement_threshold | 0.8 | agreement_threshold 或 threshold | 條目退役前,得票最多的答案需要達到的分類者佔比。大於 0 且不超過 1 |
min_classifiers | 2 | min_classifiers | 得到 needs_review 以外狀態所需的最少分類者人數。整數,至少為 1 |
schemes | 所有受支援的方案 | schemes(逗號分隔) | 要聚合的方案名。每個名稱都必須是配置中宣告的方案 |
points.eps | 0.02 | eps | 聚類半徑。大於 0;當 eps_unit 為 fraction 時不超過 1 |
points.eps_unit | fraction | eps_unit | fraction 把 x 量為影像寬度的比例、把 y 量為高度的比例,pixels 以影像畫素度量 |
points.min_samples | 2 | min_samples | 一個點成為核心點所需的、位於其 eps 範圍內的最少點數。計數包含該點自身。整數,至少為 1 |
boxes.iou_threshold | 0.5 | iou_threshold | 一組中任意兩個框之間的最小 IoU。大於 0 且不超過 1 |
當某個值超出範圍、某個鍵不在該塊的鍵列表中,或 schemes 中的某一項指向配置未宣告的方案時,伺服器會在啟動時停止,並列印一條指明該鍵的訊息。python -m potato.validate_cli config.yaml 會在研究開始之前報告同樣的錯誤。
匯出命令
匯出讀取配置以及儲存在 output_annotation_dir 下的標註:
python -m potato.export -c config.yaml -f consensus -o consensus_out該命令把 consensus.json 以及與配置中方案類型對應的 CSV 檔案寫入 consensus_out/。傳入 --option 可以在單次執行中覆蓋該塊的某項設定,而不修改配置:
python -m potato.export -c config.yaml -f consensus -o consensus_out \
--option agreement_threshold=0.9 --option eps=8 --option eps_unit=pixels遇到未知的選項名時,匯出會停止並列印已知名稱的列表。如果配置中沒有受支援類型的方案,或者沒有儲存任何標註,匯出也會停止並列印原因。對於無法通過 shell 訪問伺服器的團隊,/admin/api/export 處的管理員匯出 API 以格式名 consensus 提供同樣的匯出。
選擇題
對於每個條目和問題,匯出統計分類者人數,以及給出每個答案的標註者人數。每個答案的佔比等於該答案的人數除以分類者人數。對於單選題,各佔比之和為 1。對於 multiselect,每個佔比是勾選該選項的分類者所佔的比例,各佔比之和可以大於 1。consensus_questions.csv 每個條目和問題佔一行。以下各行來自本頁末尾介紹的示例項目:
instance_id,schema,type,n_classifiers,top_answer,top_count,top_fraction,tied,status,reason
9001,T0,radio,5,Yes,4,0.8,,retired,
9001,T1,multiselect,5,Ice,4,0.8,,needs_review,no agreement on Water (ticked by more than 20% and fewer than 80% of classifiers)
9002,T0,radio,4,Yes,2,0.5,Yes;No,needs_review,"tie between Yes, No"
9002,T1,multiselect,4,Rock,4,1.0,,retired,
9003,T0,radio,1,Yes,1,1.0,,needs_review,"1 classifier, fewer than min_classifiers (2)"
9003,T1,multiselect,1,Ice,1,1.0,,needs_review,"1 classifier, fewer than min_classifiers (2)"狀態遵循三條規則:
- 分類者過少: 分類者少於
min_classifiers的條目為needs_review。 - 單選題: 對於
radio、select或likert條目,當得票最多的答案佔比至少達到agreement_threshold,且沒有其他答案與之平票時,條目為retired。 - 多選題: 當每個選項都已確定時,條目為
retired。一個選項在至少agreement_threshold比例的分類者勾選了它,或至少同樣比例的分類者沒有勾選它時,即為已確定。
在影像 9001 上,五名標註者中有兩名勾選了 Water。因此 Water 選項仍未確定:勾選 Water 的 40% 和未勾選 Water 的 60% 都沒有達到 0.8 的閾值。出現平票時,top_answer 按方案宣告標籤的順序給出第一個平票答案,tied 用分號分隔列出所有平票答案。reason 列說明條目為何需要複核。
共識狀態只是一份報告,Potato 不會根據狀態採取任何操作。Zooniverse 在物件收到設定數量的分類後讓其退役,而 Potato 無論共識狀態如何,都會按研究的分配規則繼續分配條目。可以用狀態來挑選需要發給更多標註者或交付裁定的條目。
consensus_votes.csv 每個條目、問題和答案佔一行,列為 instance_id, schema, answer, count, fraction, n_classifiers。方案宣告的每個選項都有一行,沒有標註者選擇的選項人數為 0:
instance_id,schema,answer,count,fraction,n_classifiers
9001,T0,Yes,4,0.8,5
9001,T0,No,1,0.2,5
9001,T0,Unsure,0,0.0,5
9001,T1,Ice,4,0.8,5
9001,T1,Water,2,0.4,5
9001,T1,Rock,1,0.2,5如果儲存的多選記錄列出了選項但一個都沒有勾選,就算作一名沒有投票的分類者。這樣的記錄使 n_classifiers 加一,但不增加任何答案的人數。沒有該問題任何條目的記錄不算作分類者。
滑塊題與數字題
consensus_numeric.csv 每個條目和問題佔一行,列為 instance_id, schema, type, n, mean, median, sd, min, max。n 是給出數值答案的標註者人數。sd 是分母為 n − 1 的樣本標準差。只有一名標註者作答時,sd 為空。數值題沒有狀態。
點聚類
DBSCAN(density-based spatial clustering of applications with noise,基於密度的含噪聲空間聚類)把彼此靠近的點歸為一組,並把孤立的點作為噪聲排除在外。匯出把所有標註者在同一條目上同一標籤的點彙集在一起,再用 DBSCAN 對彙集後的點聚類:
- 若一個點與其
eps範圍內的其他點合計至少有min_samples個,該點就是核心點。 - 一個簇由一組相互連通的核心點,加上位於其中某個核心點
eps範圍內的其他點構成。緊鄰兩個簇的點加入先找到的那個簇,順序取決於標註的載入順序。 - 其餘的點都是噪聲。
這條規則與 scikit-learn 的 DBSCAN 所實現、panoptes_aggregation 的 reducer point_reducer_dbscan 所呼叫的規則相同。在 eps_unit: pixels 且 eps 和 min_samples 相同的情況下,匯出給出的簇和中心與 point_reducer_dbscan 相同。panoptes_aggregation 預設 eps 為 5 畫素、min_samples 為 3,而 Potato 的預設值適合每個條目只有少數幾名標註者的情形。如果每張影像有很多志願者,請調高 min_samples。
consensus_points.csv 每個條目、方案、標籤和簇佔一行:
instance_id,schema,label,cluster,x,y,x_px,y_px,size,n_annotators,spread,spread_px,var_x,var_y,cov_xy,annotators,label_points,label_annotators,label_noise,n_classifiers,note
9001,T2,Adult,0,0.10025,0.201,100.25,100.5,4,4,0.003897,2.331845,2.916667,4.333333,-1.166667,vol1;vol2;vol3;vol4,8,4,1,4,
9001,T2,Adult,1,0.800667,0.8,800.666667,400.0,3,3,0.004643,3.681787,16.333333,4.0,8.0,vol1;vol2;vol4,8,4,1,4,
9002,T2,Adult,,,,,,,,,,,,,,1,1,1,1,no cluster (every point is noise)在影像 9001 上,四名標註者放置了八個 Adult 點。其中七個點構成兩個簇,每個簇對應一隻成年企鵝,第八個點是噪聲。各列含義如下:
| 列 | 含義 |
|---|---|
cluster | 該條目上該標籤內的簇編號,從 0 開始 |
x, y | 簇中心,即成員點的均值,以影像寬度和高度的比例表示 |
x_px, y_px | 以畫素表示的同一中心,影像尺寸未知時為空 |
size | 簇中的點數 |
n_annotators, annotators | 在該簇中有點的不同標註者人數,以及這些標註者的名字 |
spread, spread_px | 成員點到中心距離的均方根,分別以比例和畫素表示 |
var_x, var_y, cov_xy | x 和 y 的樣本方差以及 x 與 y 的協方差,影像尺寸已知時以畫素為單位。這些值與 Zooniverse reducer 的 clusters_var_x、clusters_var_y 和 clusters_var_x_y 列一致 |
label_points, label_annotators, label_noise | 該條目上整個標籤的點數、標註者人數和噪聲點數,在該標籤的每一行上重複 |
n_classifiers | 在該條目上儲存了影像方案的標註者人數 |
note | 標籤沒有簇的原因 |
如果一個標籤的點全部是噪聲,它仍會得到一行,cluster 為空並帶有 note,如影像 9002 所示。DBSCAN 並不阻止同一名標註者的兩個點落入同一個簇。比較 size 與 n_annotators 即可找出這類簇。
影像尺寸與 Zooniverse 匯入
Potato 把每個標記都儲存為影像寬度和高度的比例。因此在 eps_unit: fraction 下,匯出無需影像尺寸即可對每個條目上的點聚類。在一張 1000 × 500 畫素的影像上,0.02 的 eps 在水平方向相當於 20 畫素,在豎直方向相當於 10 畫素。
畫素輸出和 eps_unit: pixels 都需要影像尺寸。匯出從條目的 image_width 和 image_height 欄位(或 width 和 height)獲取尺寸。沒有這些欄位時,如果影像檔案位於任務的媒體目錄下,匯出會從影像檔案本身讀取尺寸。遠端影像不會被下載。在 eps_unit: pixels 下,尺寸未知條目上的標籤會得到一行,附註為 "image size unknown; pixel eps cannot be applied",匯出還會列印一條警告,列出至多五個這樣的條目。
Zooniverse 的物件是託管在 Zooniverse 伺服器上的影像,匯出無法開啟這些伺服器上的影像。從 Potato 2.13.0 起,對於含有繪製任務的項目,potato import 會在每個條目上寫入 image_width 和 image_height。尺寸來自 Zooniverse 隨分類結果記錄的影像尺寸,或來自物件後設資料中的寬和高。因此匯入的繪製結果可以按畫素聚類,所用的 eps 與團隊在 panoptes_aggregation 中使用的相同。匯入時請加上 --keep-annotators。加上這個參數後,匯入器會把每名志願者的分類結果寫成該志願者自己儲存的標註,共識匯出隨後對每名志願者只計一次:
potato import -i zooniverse-exports/ -o my-project --keep-annotators
python -m potato.export -c my-project/config.yaml -f consensus -o consensus_out未登入的志願者顯示為 anon_<id>,因此同一個人可能被算作多名分類者。沒有記錄尺寸的物件上的標記會在匯入時被丟棄,匯入過程會統計被丟棄的標記數並列印警告。Zooniverse 匯入一節列出了匯入器能讀取的任務類型。
共識框
交併比(IoU)是兩個框的公共面積除以兩個框合起來覆蓋的面積。匯出把同一條目上同一標籤的框分成若干組。每組中每名標註者至多有一個框,組內每一對框的重疊都至少達到 iou_threshold。匯出分三步建組:
- 每個剩餘的框各自發起一個候選組,其他標註者的剩餘框按與該首個框的 IoU 從高到低依次嘗試。一個框與組內已有的每個框的 IoU 都達到閾值時,即加入該組。
- 保留最大的候選組。規模相同時,選與首個框 IoU 之和更大的組,再相同則選首個框更靠前的組。
- 被保留組中的框從池中移出,對剩餘的框重複上述步驟。不與任何其他框重疊的框自成一組。
兩個框若都與第三個框重疊、彼此卻不重疊,最終會落入不同的組。共識框取成員框左、上、右、下四條邊各自的中位數。影像被拉伸時 IoU 不變。因此分組無需影像尺寸,影像尺寸已知時會填入畫素列。
consensus_boxes.csv 每個條目、方案、標籤和組佔一行:
instance_id,schema,label,group,x,y,width,height,x_px,y_px,width_px,height_px,support,n_classifiers,support_fraction,mean_iou,min_iou,annotators
9001,T2,Nest,0,0.2,0.2,0.1,0.11,200.0,100.0,100.0,55.0,3,4,0.75,0.85617,0.826087,vol1;vol2;vol3
9001,T2,Nest,1,0.6,0.6,0.05,0.1,600.0,300.0,50.0,50.0,1,4,0.25,1.0,1.0,vol4
9003,T2,Nest,0,0.01,0.04,0.03,0.08,10.0,20.0,30.0,40.0,1,1,1.0,1.0,1.0,vol1x、y、width 和 height 以影像比例給出共識框,_px 列以畫素給出同一個框。support 是該組中的標註者人數,n_classifiers 是在該條目上儲存了影像方案的標註者人數,support_fraction 等於 support 除以 n_classifiers。mean_iou 和 min_iou 將每個成員框與共識框比較。在影像 9001 上,四名標註者中有三名畫出了第一個巢,與中位數框的平均 IoU 為 0.86;另一名標註者的框與其他任何框的重疊都未達到閾值,自成一組。
這種分組方法是 Potato 自己的,並非 Zooniverse 框 reducer 的移植。panoptes_aggregation 的 rectangle_reducer 以畫素為單位,對每個框的 x、y、寬和高執行 DBSCAN。shape_reducer_dbscan 在 metric_type: IoU 下以 1 − IoU 為距離執行 DBSCAN,一串相互重疊的框可能把兩個彼此並不重疊的框連到一起。因此,對於同一批分類結果,Potato 和 Zooniverse 得出的框共識可能不同。
文本及其他答案類型
共識匯出讀取七種方案類型:radio、select、likert、multiselect、slider、number 和 image_annotation。自由文本、片段以及其他所有方案類型都不參與共識,也不會給出警告。要進一步縮小範圍,請設定 schemes。文本答案沒有可計的票,表格匯出會保留每名標註者的文本,便於並排閱讀或用於裁定。
在 image_annotation 方案內,匯出只聚合點和框。多邊形、折線、橢圓、自由形狀、掩碼和關鍵點組按類型計數,匯出會在一條警告中列出這些計數。consensus.json 在 not_aggregated 下記錄同樣的計數。
輸出檔案
| 檔案 | 每行對應 | 寫出條件 |
|---|---|---|
consensus_questions.csv | 條目與問題 | 配置中有 radio、select、likert 或 multiselect 方案 |
consensus_votes.csv | 條目、問題與答案 | 同上 |
consensus_numeric.csv | 條目與問題 | 配置中有 slider 或 number 方案 |
consensus_points.csv | 條目、方案、標籤與點簇 | 配置中有 image_annotation 方案 |
consensus_boxes.csv | 條目、方案、標籤與框組 | 同上 |
consensus.json | 以上結果的巢狀形式,附帶所用設定、not_aggregated 計數和警告 | 總是寫出 |
CSV 檔案中的數值保留六位小數。annotators 和 tied 等列表用分號連線。consensus.json 保留完整數值以及每個問題的分類者列表。
示例
python potato/flask_server.py start examples/image/zooniverse-aggregation/config.yaml -p 8000這個示例是一個虛構的企鵝計數工作流,從 Zooniverse 匯出檔案匯入,包含五名志願者在四張群落影像上儲存的分類結果。本頁的 CSV 行來自對該示例執行共識匯出的結果,在 Potato 原始碼目錄中用 python -m potato.export -c examples/image/zooniverse-aggregation/config.yaml -f consensus -o consensus_out 執行。
延伸閱讀
- 聚合眾包標籤 - Dawid-Skene、MACE,以及何時保留答案的分佈
- MACE 能力估計 - 面向類別型方案的能力加權標籤
- 如何測量邊界框上的標註者間一致性 - 空間標籤上經過機遇校正的一致性
- 匯出格式 - Potato 的匯出格式和匯出命令
- 生態學 - 用 Potato 做紅外相機與生物聲學標註
實現細節參見源文件。