コンテンツへスキップ

一致度のドリフトと再較正ラウンド

Potato は /admin/iaa で、完了したアイテムのウィンドウごとに一致度を採点し、プロジェクトのベースラインを下回る低下にフラグを立て、コーダーを訓練に戻します。

Potato は、完了したアイテムの連続するウィンドウごとにコーダー間一致度を採点するため、最近のコーディングでの低下は、プロジェクト全体の一つの数値に平均されてしまわず、一致度レポートで低いウィンドウとして現れます。プロジェクト全体の係数は、最初の週のコーディングと最後の週のコーディングを混ぜるため、最近の作業の質が下がったチームでも、許容できる α を報告できてしまいます。/admin/iaa の Agreement over time セクションは、各アノテーションスキームの係数をウィンドウごとに示し、直近のウィンドウがプロジェクトのベースラインを一定の割合以上下回ると、再較正のプロンプトを出します。再較正ラウンドは、その後コーダーを訓練アイテムに戻し、既知の正解に照らして回答を採点します。このタイムラインとラウンドは Potato v2.9.0 から提供されており、タイムラインはデフォルトでオンです。

ここでのドリフトは、調査の過程でコーダーがコードブックを適用する方法が徐々に変わることを指します。ドリフトは、新しい境界事例が現れ、各コーダーが定義について自分なりの読み方に落ち着くにつれて積み重なります。コーディングの開始前の一回のコーダー間信頼性のチェックでは、ドリフトを検出できません。Hennessy、Bleakley、Ellithorpe(2022)が引用している一節で、Lacy ら(2015)は「コーダー間信頼性のチェックは、研究の内容がコーディングされる際に、その内容を使って行われるべきである」と書いています。同じ懸念は、ラベルの集合が増えるにつれてガイドラインが変わる、ML のラベル付けチームにも当てはまります。このページは、調査の進行中の一致度を扱い、時間セグメントに対する一致度は、音声や動画で開始時刻と終了時刻に印を付けるアノテーターを扱います。

ウィンドウの境界とアイテムのタイムスタンプ

一致度は、一人のコーダーの回答ではなく、コーダーをまたぐアイテムに属します。そのため Potato は、各アイテムを、そのアイテムの最後のコーダーが終えた時点を含むウィンドウに置きます。その時点は、そのアイテムに、比較できる完全な回答の組が初めてそろった時点です。アノテーター数の上限に達したアイテムだけがタイムラインに入り、その上限は二以上でなければなりません(たとえば num_annotators_per_item: 2)。プロジェクト全体の一致度の表は、同じアイテムを使います。そのため各ウィンドウは、ベースラインの基になったアイテムの一部を含みます。

コーダーがアイテムを終えた時点は、そのスキームの回答への最後の記録された変更です。アイテムに記録された変更がない場合、Potato は、コーダーがそのアイテムを離れた時刻に、さらにそれがなければコーダーがそのアイテムを開いた時刻に切り替えます。開いた時刻は最後の手段です。キューをざっと眺めて後から回答するコーダーは、各アイテムを回答のずっと前に開いているためです。タイムスタンプがまったくないアイテムはタイムラインに載らず、セクションはその数を報告します。他のツールからインポートしたアノテーションが、その典型的な場合です。

アイテムはその時点で並べ替えられ、二つの方法のいずれかでウィンドウに切り分けられます。

  • 等数(window_by: count、デフォルト)。すべてのウィンドウが同じ数のアイテムを持ちます。ウィンドウの数は、アイテムの数が上限です。したがって、五アイテムのパイロットでは、空のウィンドウは生じません。
  • 等期間(window_by: time)。すべてのウィンドウが、同じ長さの時計上の時間にわたります。コーディングが、たとえば一か月離れた二回の週末のように、まとまって行われる場合、そのまとまりの間のウィンドウは空になります。空のウィンドウには一致度の値がまったくありません。一致度のページの表では、空のウィンドウは、コーディングが行われなかったのに一致度が崩壊したように見えてしまうため、そのために等数がデフォルトです。

各ウィンドウが報告する係数

Potato は、各ウィンドウ自身のアイテムに対して、プロジェクト全体の一致度の計算を再実行します。そのため、あるスキームについて、すべてのウィンドウとベースラインは、同じ係数を使います。Potato はスキームごとに一つの代表的な係数を選び、偶然補正済みの指標を優先します。百分率一致は、クラスの不均衡だけで上昇し、コーダーの一致が偶然から予測される水準を下回っていても、上昇傾向を示すことがあります。係数はスキームのタイプによって決まります。

スキームタイプタイムラインでの係数
radio、select(抜粋ごとに一つのコード)Krippendorff の α、名義
likertKrippendorff の α、順序
slider、numberKrippendorff の α、間隔
multiselect、hierarchical_multiselect(抜粋ごとに複数のコード)MASI 距離を用いた Krippendorff の α
span(コーディングされた箇所)位置 α。位置 α が未定義の場合はトークンレベルの κ
multirate とその他のグリッドスキームすべての行でプールした α
α のないスキームFleiss の κ、Cohen の κ、重み付き κ、相関または ICC、スパン F1、百分率一致のうち、最初に利用可能なもの

Krippendorff の α は、完全な一致で 1、偶然が生み出す水準の一致で 0 です。textbox のような自由記述のスキームには一致度の指標がなく、タイムラインに行は表示されません。ウィンドウのデータが、ベースラインの使う係数を算出できない場合、セルは別の指標ではなく、値なしを表示します。二つの異なる指標の間の低下は、意味を持たないためです。

タイムラインのセルとセルの注記

各スキームに一行が割り当てられます。行は、ベースラインとしてのプロジェクト全体の係数で始まり、その後に、ウィンドウごとに一つのセル(W1、W2 など)が続き、そのウィンドウの係数とアイテム数を示します。数値のないセルには、代わりに短い注記が表示され、Potato はタイムラインの表の下で、それぞれの注記を説明します。アイテムが少なすぎるウィンドウは、値を表示し、マーカーを追加します。注記とマーカーの意味は次のとおりです。

注記意味
total agreementウィンドウ内のすべてのアイテムで、すべてのコーダーが同じコードを選びました。偶然補正済みの係数には補正すべきものがなく、未定義になります。この注記は、一致度の最良のケースを示します。
undefinedウィンドウのデータでは係数が未定義で、最も多いのは、一つのコードがすべての判断を占めている場合です。
no overlapウィンドウのアイテムで重なったコーダーが二人未満でした。
no itemsウィンドウにアイテムが入りませんでした(等期間のウィンドウのみ)。
too few to judgeウィンドウのアイテムが五つ未満です。値は表示されますが、再較正のプロンプトはそのウィンドウを無視します。

プロジェクトが QDA モードのコードブックを使っている場合、表の下の一行に、コードブックの改訂(r1 · r2 · r3)が一覧されます。Potato は、コードブックの変更のたびに改訂番号を上げます。コードの作成、名前変更、色の変更、移動、削除は、それぞれ変更として数えられます。v2.9.0 以降に記録された改訂には、正確な時刻があります。それより古い改訂は、その改訂を刻印された最も早いアノテーションから日付が付けられます。その日付は下限であり、改訂には approximate というラベルが付きます。HTML ページは改訂を番号で一覧し、下の JSON レポートは各改訂の時刻を示します。スクリプトを使えば、各コードブックの編集をウィンドウの境界と照らして、ガイドラインの変更が一致度を動かしたかどうかを確認できます。

設定

タイムラインに設定は不要です。アイテムごとに二人以上のコーダーがいて、一致度の報告があるプロジェクトでは、/admin/iaa にこのセクションが表示されます。管理ダッシュボードは、このページを完全な一致度レポートとしてリンクしています。デフォルトを変更するには、既存の設定に calibration ブロックを追加します。

yaml
calibration:
  enabled: true
  windows: 6
  window_by: count
  drop_threshold: 0.15

calibration は、まさにこの四つのキーを取ります。

キー型デフォルトキーの役割
enabledbooleantrue/admin/iaa を読み込むたびにタイムラインを計算します。セクションをオフにするのは false のみです。
windowsinteger6ウィンドウの数。六つのウィンドウは、傾向を示しつつ、各ウィンドウに偶然補正済みの係数を算出するのに十分なアイテムを残します。等数モードでは、この数はアイテム数が上限です。
window_bystringcount等しい大きさのウィンドウには count、等しい期間のウィンドウには time。それ以外の値は count として扱われます。
drop_thresholdnumber0.15再較正のプロンプトを出す、ベースラインを下回る相対的な低下。0.15 は、プロジェクト全体の係数を 15% 下回ることを意味します。

タイムラインは、/admin/iaa を読み込むたびに、ウィンドウごとに一回の追加の一致度の計算を必要とします。enabled: false を設定すると、大規模なプロジェクトではそのコストがなくなります。その場合、タイムラインは /admin/iaa と /admin/iaa/drift の JSON レポートの両方から消えます。

再較正ラウンドは、訓練フェーズを再実行します。そのため、ラウンドを実行するプロジェクトには、training が有効で、phases に training の項目が必要です。以下の設定は、回答ごとに一つのコードを付ける、自由記述式のアンケート回答についての、二人のコーダーによる完全な調査です。

yaml
annotation_task_name: Open-ended responses, two coders
task_dir: .
output_annotation_dir: annotation_output/
data_files: [data/responses.json]
item_properties: {id_key: id, text_key: text}
 
annotation_schemes:
  - annotation_type: radio
    name: barrier
    description: Which barrier to care does the respondent describe?
    labels: [Cost, Distance, Wait time, Trust, None]
 
num_annotators_per_item: 2
 
training:
  enabled: true
  data_file: data/training.json
  allow_retry: true
  failure_action: repeat_training
 
phases:
  order: [training, annotation]
  training: {type: training}
  annotation: {type: annotation}
 
agreement_metrics: {enabled: true}
 
calibration:
  windows: 6
  window_by: count
  drop_threshold: 0.15

num_annotators_per_item: 2 は、すべての抜粋を両方のコーダーの前に置きます。抜粋ごとに二人のコーダーがいれば、各ウィンドウに一致度の値が得られます。failure_action: repeat_training は、ラウンドに不合格だったコーダーの参加を終了する代わりに、そのコーダーの訓練アイテムをやり直させます。訓練ファイルには、訓練フェーズのページが説明する形式で、合意されたコードと説明を持つ抜粋が入っています。

再較正のプロンプト

Potato は、各スキームの直近のウィンドウをベースラインと比較し、相対的な低下が drop_threshold に達するとプロンプトを出します。相対的な低下は (ベースライン − 直近) / ベースライン です。ベースラインは、最初のウィンドウではなくプロジェクト全体の係数です。訓練されたばかりのチームの一致度は、最初のウィンドウで最も不安定だからです。そうでなければ、異常によい最初のウィンドウが、調査全体の基準を決めてしまいます。ベースラインの α が 0.720 で、直近のウィンドウが 0.580 の場合、低下は 19% で、セクションには次のように表示されます。

text
Re-calibration suggested — barrier 19% below the project baseline (alpha_nominal 0.580 vs 0.720).

このプロンプトは、チームリードへの助言です。プロンプトはコーダーに通知せず、ラウンドも開始しません。Potato は、三つの場合にはプロンプトを出しません。

  • 以前の落ち込み。 Potato が判断するのは、アイテムが五つ以上ある直近のウィンドウのみです。チームがすでに回復した落ち込みについてのプロンプトは、チームにプロンプトを無視することを教えてしまいます。
  • 直近のウィンドウが未定義。 直近のウィンドウが total agreement または undefined を示している場合、Potato はより古いウィンドウには切り替えません。
  • ベースラインがゼロ以下。 すでに偶然の水準にある一致度は、プロジェクト全体の表が報告する問題であり、ゼロからの割合での低下には意味がありません。

管理 API を通じた較正ラウンドの開始

ラウンドは、指名された各コーダーの訓練の進捗をリセットし、そのコーダーを訓練フェーズに戻します。コーダーは、同じ訓練アイテムをもう一度こなします。Potato は、最初のパスと同じように、同じ正解に照らして回答を採点し、誤答ごとに説明を表示します。合格後、コーダーは phases.order で訓練の次にあるフェーズに進み、中断したところから再開します。ラウンドは、割り当ても保存されたアノテーションも変えません。Potato は、ラウンドが始まったことを知らせるメッセージをコーダーに表示しません。ラウンドを開始する前に、チームに知らせてください。

ラウンドは、管理 API キーを使って管理 API を通じて開始します。管理ページには、ラウンドを開始するボタンがありません。キーの入手先は、管理ダッシュボードのページで説明されています。誰が対象になるか、また直近のラウンドがどう進んだかを確認します。

bash
curl -H "X-API-Key: $KEY" http://localhost:8000/admin/calibration

レスポンスには、ラウンドが呼び戻せるコーダー、過去のラウンド、および直近のラウンドでの、呼び戻された各コーダーの進捗が一覧されます。進捗は、passed、failed、in_progress、unknown のいずれかで、回答数、合計数、正解数が付きます。アノテーションフェーズ、研究後フェーズ、または完了フェーズにいるコーダーが対象です。対象となるすべてのコーダーのラウンドを開始します。

bash
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
     -d '{"reason": "barrier alpha fell 19%"}' \
     http://localhost:8000/admin/calibration/start

この呼び出しは、ラウンドの ID、呼び戻されたコーダー、そして理由付きでスキップされたコーダーを返します。名前を指定したコーダーだけを呼び戻すには、"usernames": ["coder1", "coder2"] を渡します。usernames を省略すると、対象となる全員が呼び戻されます。ガイドラインのドリフトはチーム全体に影響します。そのため、全員を呼び戻すのが通常は適切な選択です。

同意または説明のページにまだいるコーダーは、レスポンスの skipped の下に一覧されます。training が有効でない場合、この呼び出しは誰も呼び戻さず、HTTP 400 を返します。訓練アイテムがなければ、呼び戻されたコーダーは、空の訓練フェーズをそのまま通過してしまうためです。

最初のラウンドの前に、訓練の設定を計画してください。理由は二つあります。第一に、ラウンドに不合格だったコーダーは、training.failure_action によって扱われます。デフォルトの move_to_done のもとでは、ラウンドに不合格だとそのコーダーの調査への参加が終わります。最初のパスに不合格だった場合も、同じ結果になります。代わりに訓練アイテムをやり直させるには、failure_action: repeat_training を設定してください。第二に、ラウンドは訓練アイテムを ID で選び、各コーダーに、そのコーダーが最初に見たアイテムを表示します。コーダーの最初のパスの後にファイルへ追加された訓練アイテムは、ラウンドではそのコーダーに届きません。難しい事例は、コーディングを始める前に訓練ファイルに入れておいてください。

チームが不一致を議論する場所

ラウンドは、訓練アイテムに採点の基準となる既知の答えがあるため、訓練アイテムを再実行します。調査自身の不一致のアイテムには、正しい答えがありません。そのため Potato は、それらのアイテムをラウンドに含めません。再較正の議論の側は、Potato の別の場所で行われます。マルチプレイヤールームのハドルルームは、チームが現在意見の分かれているアイテムを順に確認し、すべてのコーダーの元のコードを表示します。裁定のキューでは、裁定者が、争いのあるアイテムを一つずつ解決します。定性研究のチームは、通常、その議論をコードブックのコード定義の改訂で終え、次の改訂は、その後のウィンドウの隣のタイムラインに表示されます。

ドリフトレポートとラウンドログ

ドリフトレポートとラウンドログは、アノテーションのエクスポートとは別です。python -m potato.export のどの形式にも、ドリフトレポートやラウンドログは含まれません。タイムラインを JSON として取得します。

bash
curl -H "X-API-Key: $KEY" http://localhost:8000/admin/iaa/drift

JSON レポートには、次のフィールドがあります。

  • windows は、各ウィンドウのインデックス、開始時刻と終了時刻、アイテム数、sparse フラグ、アイテム ID、そしてそのウィンドウに限定した完全な一致度レポートを一覧します。
  • schemas は、スキームごとに、代表的な指標、ベースライン、そしてウィンドウごとに、そのウィンドウの値、注記、アイテム数を持つ一点を示します。
  • triggers は、プロンプトを出したすべてのスキームを、ベースライン、直近の値、相対的な低下とともに一覧します。
  • markers は、コードブックの改訂を、各改訂の時刻と、おおよその日付のための inferred フラグとともに一覧します。
  • n_items と n_untimed_items は、タイムライン上のアイテムと、タイムライン外のアイテムを数え、reason は空のレポートの理由を説明します。

時刻は秒単位の Unix タイムスタンプです。比較するものがない場合、たとえばアノテーター数の上限に達したアイテムがない場合や、時刻のあるすべてのアイテムが一つのウィンドウに入る場合、レポートは空になります。その場合、reason フィールドが理由を述べます。

Potato は、各ラウンドを <task_dir>/project.sqlite の calibration_rounds テーブルに、ラウンドの開始時刻、ラウンドを開始した管理者(API キーでの呼び出しでは admin)、理由のテキスト、呼び戻されたコーダーとともに記録します。ラウンドログとウィンドウごとの係数は、方法のセクションに、各再較正の日付と、各ラウンドの前後の一致度を提供します。定性研究の監査証跡には、両方の記録が必要です。コーダーの訓練の回答は user_state.json にあり、各ラウンドはそれらの回答をリセットします。最初のパスの訓練スコアを残すには、ラウンドの前に、アノテーションの出力ディレクトリのコピーを保存してください。

関連資料

実装の詳細については、ソースドキュメントを参照してください。

参考文献

  • Hennessy, M., Bleakley, A., & Ellithorpe, M. E. (2022). Evaluating and tracking qualitative content coder performance using item response theory. Quality & Quantity, 57(2), 1231-1245. https://doi.org/10.1007/s11135-022-01397-7
  • Lacy, S., Watson, B. R., Riffe, D., & Lovejoy, J. (2015). Issues and best practices in content analysis. Journalism & Mass Communication Quarterly, 92(4), 791-811. https://doi.org/10.1177/1077699015607338 (quoted from Hennessy et al., 2022)