この用語と一緒に検索・参照されやすいタグ。 関連ページに飛ぶときの手がかりにも使えます。
「annotation」は統計データ分析の文脈で扱う重要概念のひとつ。 本ページでは「annotation」を取り巻く中核キーワードを以下にチップで一覧化する。 各キーワードは関連する概念・手法・道具立てを含み、 文献検索や学習計画の起点になる。
これらのキーワードは「annotation の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。
🍰 まずはやさしく
データに正解のラベルを貼る作業です。
AIに正しい答えを教えるために使います。
写真に「犬」や「猫」と名前を付けるようなことです。
この章ではアノテーションの結論を学びます。
アノテーションは、 生データに意味付け(ラベル・タグ・領域)を与える作業。 教師あり学習の出発点。
ここまでが要点です。 ただし実際に使う前に、 このページの「⚠️ よくある落とし穴」で挙げた ガイドラインが曖昧/マジョリティの偏り/過剰品質 には必ず目を通してください。 つまずくのは知識が無いときより、 知ってはいたが確認を飛ばしたときです。
🍰 まずはやさしく
AIを作る時に欠かせない準備のことです。
AIに何を判断させるかを決めるために使います。
スマホの画像認識などの機能で使われています。
この章ではどんな場面で使うかを確認します。
公的統計のような既ラベルデータでは発生しませんが、 画像認識・NLP・医療 AI などほぼ全ての応用で大コストを占めるプロセス。 「データセントリック AI」では特に重視されます。
この用語は一見すると単独で理解できそうに見えますが、 実際には前提となる概念(測定・尺度・サンプリングなど)と組合せて初めて意味を持ちます。 「定義を覚える」より「どんな問いに答える道具なのか」を捉えるのが効率的です。
🍰 まずはやさしく
データに意味を付ける仕分け作業のようなものです。
AIの性能を上げるために正解を作ります。
都道府県の画像に地方の名前を付ける例があります。
この章では直感的に仕組みを理解しましょう。
アノテーションは「生データに人間が意味(正解ラベル)を付与する工程」。 例えば 47 都道府県の画像に「東北/関東/関西/…」と地方区分を付ける、 SSDSE-B-2026 のテキスト解説に「人口」「教育」「医療」とトピックタグを振る、 などが典型例です。 後段の機械学習モデルの性能はアノテーション品質の上限で決まります。
🍰 まずはやさしく
作業の正しさを測るためのルールです。
バラつきがないかを確認するために使います。
部活の判定基準をみんなで揃えることに似ています。
この章では数式を使って定義を学びます。
やさしい説明で掴んだ感覚を、ここで アノテーター間合意(Cohen's κ) の定義式に対応づけます。下の式は左辺 $\kappa$ が何で決まるかを右辺で書き下したもので、分数(割り算) が現れます。それぞれの記号が何の量を指すのかは、次の「🔬 数式を言葉で読み解く」で 1 つずつ確かめてください。
Cohen の κ は便利な一致度指標ですが、 単独で報告するのは危険です。 ラベル分布の偏りに敏感で、 同じ実態でも分布が違うだけで κ が大きく変動する 「カッパパラドックス (Feinstein & Cicchetti 1990)」 が知られています。 SSDSE-B-2026 の都道府県分類 (47 件) のような小規模データでは特に注意が必要です。 ここでは κ の限界と、 補完的に使う 3 つの指標 (PABAK / Krippendorff α / 観測一致率) を整理します。
| 指標 | 数式概要 | 特徴 | 使い時 |
|---|---|---|---|
| 観測一致率 p_o | 同じラベルの割合 | 直感的、 偶然補正なし | 最初の報告、 分かりやすさ重視 |
| Cohen κ | (p_o - p_e) / (1 - p_e) | 偶然補正、 分布偏りに弱い | 2 名ラベラー、 名義尺度 |
| PABAK | 2·p_o - 1 | prevalence 補正版、 単純 | クラス分布が極端に偏る時 |
| Krippendorff α | 1 - D_o / D_e | 任意尺度・任意数ラベラー対応 | 3 名以上、 順序/間隔尺度 |
SSDSE-B-2026 の都道府県分類で「減少」が 28/47 (60%)、 「維持」17/47 (36%)、 「増加」2/47 (4%) のように偏りがある場合、 Cohen κ だけだと 「増加」クラスの偶然一致率が低く推定されすぎて、 一致度が過小評価 されることがあります。 この時 PABAK (= 2×観測一致率 - 1) を併報すると、 分布偏りに依存しない一致度の参考値として補完できます。
このコードでやること: SSDSE-B-2026 の都道府県分類タスクに対して、 観測一致率/Cohen κ/PABAK/Krippendorff α を同時計算します。 1 つの指標だけに依存せず、 4 つの数値を並べて解釈することで「カッパパラドックス」を回避できます。
📥 入力: 47 都道府県のラベラー A/B 判定 (3 クラス分類)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | import pandas as pd import numpy as np from sklearn.metrics import cohen_kappa_score raw = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) pop = raw.pivot_table(index='Prefecture', columns='SSDSE-B-2026', values='A1101') # 人口変化率(%): A1101 の 2013→2018(実測5年変化) df = pd.DataFrame({'人口変化率': (pop[2018] - pop[2013]) / pop[2013] * 100}) # 仮想ラベラー A/B (厳しめ閾値 ±2 と緩め閾値 ±1) def label_strict(x): if x < -2: return '減少' elif x > 2: return '増加' else: return '維持' def label_loose(x): if x < -1: return '減少' elif x > 1: return '増加' else: return '維持' df['lab_A'] = df['人口変化率'].apply(label_strict) df['lab_B'] = df['人口変化率'].apply(label_loose) # 1. 観測一致率 p_o = (df['lab_A'] == df['lab_B']).mean() # 2. Cohen κ kappa = cohen_kappa_score(df['lab_A'], df['lab_B']) # 3. PABAK (二値拡張: 多値では平均観測一致率を使う簡易版) pabak = 2 * p_o - 1 # 4. Krippendorff α (簡易版: 名義尺度) # 実用は krippendorff パッケージ推奨 from collections import Counter all_labels = pd.concat([df['lab_A'], df['lab_B']]) freq = Counter(all_labels) N = sum(freq.values()) p_e_kripp = sum((v / N) ** 2 for v in freq.values()) alpha = 1 - (1 - p_o) / (1 - p_e_kripp) if p_e_kripp < 1 else float('nan') print(f'観測一致率 p_o = {p_o:.3f}') print(f'Cohen kappa = {kappa:.3f}') print(f'PABAK = {pabak:.3f}') print(f'Krippendorff α (簡易) = {alpha:.3f}') |
📤 実行例:
💬 結果の読み方: 観測一致率 0.766 (約 8 割は一致) は直感的には「悪くない」と見えますが、 Cohen κ=0.536 / Krippendorff α=0.516 は moderate レベルにとどまる。 PABAK=0.532 も κ とほぼ同水準で、 4 指標が 0.52〜0.54 に収束します (この 3 クラス構成では分布の偏りによる乖離は小さい)。 報告書には 4 つの指標すべてを併記 し、 「moderate 一致度。 改善余地あり」と書くのが誠実です。 「一致率 77% で良好」と書くのは不誠実 (偶然一致を補正していない)。
小規模データ (n=47) では κ の点推定だけでなく信頼区間も必須です。 ブートストラップで 1,000 回リサンプリングして 2.5 / 97.5 パーセンタイルを取ります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | import pandas as pd import numpy as np from sklearn.metrics import cohen_kappa_score np.random.seed(0) # 実行のたびに同じ結果が出るようにする # この抜粋だけで動くように、ラベラー A/B のラベルをここで作り直す raw = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) pop = raw.pivot_table(index='Prefecture', columns='SSDSE-B-2026', values='A1101') df = pd.DataFrame({'人口変化率': (pop[2018] - pop[2013]) / pop[2013] * 100}) def label_strict(x): if x < -2: return '減少' elif x > 2: return '増加' else: return '維持' def label_loose(x): if x < -1: return '減少' elif x > 1: return '増加' else: return '維持' df['lab_A'] = df['人口変化率'].apply(label_strict) df['lab_B'] = df['人口変化率'].apply(label_loose) labels_A = df['lab_A'].values labels_B = df['lab_B'].values # ブートストラップ 95% CI n_boot = 1000 kappas = [] rng = np.random.RandomState(42) # 再現性のため固定 n = len(labels_A) for _ in range(n_boot): idx = rng.choice(n, size=n, replace=True) k = cohen_kappa_score(labels_A[idx], labels_B[idx]) kappas.append(k) ci_low, ci_high = np.percentile(kappas, [2.5, 97.5]) print(f'Cohen kappa = {cohen_kappa_score(labels_A, labels_B):.3f}') print(f'95% CI = [{ci_low:.3f}, {ci_high:.3f}]') |
📤 実行例:
💬 結果の読み方: 95% CI が [0.337, 0.706] と非常に幅広く、 真の κ は fair から substantial まで広い範囲 に入る可能性があります。 これは n=47 という小規模データの宿命であり、 「κ=0.536 だから moderate」と断言するのは過剰です。 報告書では 「κ=0.54 (95% CI: 0.35-0.73, n=47)」 のように サンプルサイズと CI を必ず併記 することが学術的誠実性の基本です。 SSDSE-B-2026 のような小規模公的統計を扱う際は、 CI が指標の点推定より雄弁です。
SSDSE-B-2026 規模のプロジェクト (数十〜数千件) を想定した、 全工程で参照できる 40 項目チェックリストです。 キックオフ時にチーム全員でレビューし、 各工程の完了判定に使用してください。
| 工程 | No. | チェック項目 |
|---|---|---|
| 企画 | 1 | ユースケース (誰が何のために使うラベル) が 1 文で説明できる |
| 2 | サンプル数の目標が決まっている (最低 1,000 件 / 各クラス 50 件) | |
| 3 | 予算と納期が文書化されている | |
| 4 | データソース (例: SSDSE-B-2026) のライセンス・利用規約を確認した | |
| 5 | アノテーション対象のサンプリング方法が決まっている | |
| 6 | 個人情報や機微情報を含まないことを確認した | |
| ガイドライン | 7 | 各クラスの定義が 200 字以上で明文化されている |
| 8 | クラスごとに正例が 5 件以上提示されている | |
| 9 | 境界例が 10 件以上提示されている | |
| 10 | NG 例 (よくある誤判定) が 5 件以上提示されている | |
| 11 | 外部レビュー (チーム外の専門家 1 名以上) を通過した | |
| 12 | バージョン番号と更新履歴が記載されている | |
| 13 | 操作的定義 (数値境界等) が明確に記述されている | |
| 14 | 「判定不能」の選択肢があるか、 ないなら理由が明文化されている | |
| パイロット | 15 | 3 名以上のラベラーで実施した |
| 16 | サンプル数 50 件以上で実施した | |
| 17 | Fleiss κ または Krippendorff α を計算した | |
| 18 | 客観タスク κ ≥ 0.7 / 主観タスク κ ≥ 0.5 を達成した | |
| 19 | 未達なら、 不一致サンプルを境界例としてガイドラインに追加した | |
| 20 | 所要時間の中央値・95 パーセンタイルを記録した | |
| 21 | ラベラーからのフィードバックを文書化した | |
| 22 | UI の改善ポイントを抽出した | |
| 本番 | 23 | 2 名以上のラベラーで全サンプルを多重アノテーションした (or 10% 多重化) |
| 24 | 不一致サンプルの仲裁プロセスが決まっている | |
| 25 | 週次で 5% 抜き打ち再アノテーションを実施している | |
| 26 | サンプル提示順をランダム化している | |
| 27 | 1 ラベラー/日の作業時間を 4 時間以内に制限している | |
| 28 | ガイドラインバージョンをラベルメタデータに記録している | |
| 29 | 所要時間外れ値 (3×IQR 超) を毎週レビューしている | |
| 30 | ラベラー別の中央値バイアスをモニタリングしている | |
| QA | 31 | 完了データの 10% を独立ラベラーが再アノテーションした |
| 32 | 一致率 ≥ 95% を達成した | |
| 33 | 未達バッチは全件再チェックした | |
| 34 | クラス別の分布が想定通りであることを確認した | |
| 35 | 代表的なベースラインモデルで test 性能を確認した | |
| 36 | ラベル品質レポート (κ・CI・分布) を文書化した | |
| 納品 | 37 | データセット README に必須項目 5 点 (出典/件数/ラベラー/κ/ガイドライン) を記載した |
| 38 | ガイドライン本文を附録または別ファイルで提供した | |
| 39 | 不一致サンプルとその解決方法を別ファイルで提供した | |
| 40 | ライセンス (CC BY 等) を明記した |
この 40 項目チェックリストを プロジェクト終了時に「Yes/No」で全件回答 することで、 自己点検の最後の砦になります。 1 つでも No があるなら、 該当工程に戻って補完してから納品します。 「全て Yes」でなければ 外部に出すべきではない という基準を持つことが、 アノテーション専門家としての矜持です。 SSDSE-B-2026 のような公的データを使う際もこの基準は変わりません。
アノテーションプロジェクト実務でよく寄せられる質問の拡張回答集です。 SSDSE-B-2026 のような公的データを使う際の具体的シナリオを含めて回答します。
アノテーションプロジェクトを安定的に運営するには、 役割を明確に分けることが重要です。 SSDSE-B-2026 のような小規模プロジェクトでも、 以下 5 つの役割を兼任しつつ責任範囲を明確化することで品質が安定します。
| 役割 | 主担当業務 | 必要スキル | 小規模時の兼任 |
|---|---|---|---|
| アノテーションリード | ガイドライン策定、 品質管理 | タスクドメイン知識 + 統計理解 | プロジェクトマネージャと兼任可 |
| 仲裁者 (Arbitrator) | ラベラー間不一致の最終判定 | 高ドメイン専門性 + 判断速度 | リードと兼任可 (中立性確保が課題) |
| ラベラー (Annotator) | 実際のラベル付与作業 | ガイドライン理解 + 一定の集中力 | 2-5 名、 兼任不可 |
| QA 担当 | 抜き打ち再アノテーション、 一致率監視 | 統計分析 + ラベル作業経験 | 仲裁者と兼任可 |
| ツール管理者 | アノテーション UI のメンテ、 進捗ダッシュボード | エンジニアリングスキル | 外部ツール (Label Studio 等) 利用なら省略可 |
SSDSE-B-2026 の都道府県分類 (47 件) なら リード兼仲裁者 1 名 + ラベラー 2 名 + QA 兼任 1 名 = 計 3-4 名 で 1 週間以内に完了可能。 アノテーションリードは 「ラベラーに直接作業させない」 ことが鉄則 (定義者と判定者を分離することで「定義の自己肯定バイアス」を排除)。 仲裁者がリードと別人であれば最も理想的ですが、 小規模では現実的な兼任で運用します。
役割分担を明文化するだけで、 アノテーション工程の混乱・遅延・品質劣化の 大部分を予防 できます。 「誰が何の責任を負うか」が曖昧なまま走り出すプロジェクトの多くは、 途中で品質崩壊を起こします。 SSDSE-B-2026 のような公開データを扱うプロジェクトでも、 役割分担は必須の準備項目です。
アノテーション工程の生産性と品質はツール選定に大きく依存します。 SSDSE-B-2026 のような表形式公的データから画像/テキスト/時系列まで、 タスク特性に応じた代表ツールを整理します。
| ツール | 得意タスク | ライセンス | SSDSE-B-2026 向けの適性 |
|---|---|---|---|
| Label Studio | 汎用 (画像/テキスト/表/音声) | OSS (Community 版無料) | ◎ 表データの 3 クラス分類に最適 |
| doccano | テキスト分類/NER | OSS (MIT) | ○ 都道府県名+説明文のテキスト分類用途 |
| CVAT | 画像/動画の物体検出/セグメント | OSS (MIT) | △ 表データには不向き |
| Prodigy | テキスト+アクティブラーニング | 商用 (390 ドル〜) | ○ 中規模テキストアノテーション |
| Google Sheets + Apps Script | 小規模 (~500 件) の表分類 | 無料 (Google アカウント) | ◎ SSDSE-B-2026 (47 件) なら最速立ち上げ |
| Amazon SageMaker Ground Truth | 大規模 + クラウドソーシング統合 | 商用 (従量課金) | △ 小規模ではオーバースペック |
SSDSE-B-2026 規模 (47 件) なら Google Sheets + 簡易スクリプト または Label Studio が最速で立ち上げ可能。 ツール選定の判断基準は (a) サンプル数、 (b) タスク形式、 (c) チームの技術スタック、 (d) 予算 の 4 軸。 「すごいツール」を入れることが目的化しないよう、 最小限のツールで開始し必要が出てから拡張 する原則を推奨します。 ツール導入のセットアップ時間がアノテーション工程のクリティカルパスにならないよう注意してください。
アノテーションは 「データを作る」工程 であり、 モデル性能の上限を決める最重要工程です。 SSDSE-B-2026 のような公的データを使う場合でも、 ラベル付けの工程設計を疎かにすると下流の分析全体が崩れます。 本補遺の三層モニタリングと 8 つの落とし穴チェックを、 プロジェクトキックオフ時の必読リストに組み込んでください。
最後に強調しておきたいのは、 アノテーション品質は 「数字 (κ や F1) だけで評価できない」 という点です。 ガイドラインの読みやすさ、 ラベラーへの心理的安全性、 仲裁プロセスの透明性、 ツール UI の使いやすさ、 こういった 定性的要因がラベル品質の 30-40% を決めている という現場感覚があります。 数値指標は重要な羅針盤ですが、 同時にラベラー本人の声に耳を傾け、 ガイドラインを生きた文書として更新し続ける姿勢が、 アノテーションプロジェクトを成功に導く真の鍵です。 SSDSE-B-2026 規模の小さなプロジェクトであっても、 この姿勢を持つチームが作るラベルは、 確実に分析の質を引き上げます。 アノテーションは技術と人間性の交差点に位置する、 データサイエンスの根幹工程なのです。 SSDSE-B-2026 を題材とした本ページのチェックリストと指標群を、 まずは自分のプロジェクトに 1 項目ずつ適用してみることから、 アノテーション品質改善の旅は始まります。 完璧を求めず、 1 工程ずつ着実に改善する姿勢が、 結果的に最も高い品質に到達する近道です。
数式を眺めるだけでは身につかないので、 各記号がどんな役割を担っているかを言葉で押さえます。 「数式を音読する習慣」がつくと、 論文や教科書を読むスピードが体感で 2 倍ほど上がります。
アノテーションは「正解ラベルを付ける作業」ですが、 実務では 「複数の人が同じ基準で同じラベルを付けられるか」 が品質の核心です。 ここでは SSDSE-B-2026 の 47 都道府県を題材に、 「人口階層(大都市/中都市/小都市の 3 クラス)」を 3 人のアノテーターが付ける状況をシミュレートし、 アノテーター間一致度(Cohen's kappa, Fleiss' kappa)を算出します。 これは実際の AI プロジェクトで「ラベルガイドラインの妥当性検証」として必ず行う作業です。
このコードでやること:SSDSE-B-2026 の総人口(A1101)を読み込み、 3 人の架空のアノテーター(A・B・C)がそれぞれ違う基準で「大/中/小」クラスを付けたという想定で、 Cohen's kappa を A-B, A-C, B-C で測り、 Fleiss' kappa で 3 人全体の合意度を計算する。
📥 入力データ(SSDSE-B-2026 から都道府県 47 件の総人口を抽出):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import pandas as pd import numpy as np from sklearn.metrics import cohen_kappa_score df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[(df['SSDSE-B-2026'] == 2023) & df['Code'].str.endswith('000')] # 2023 年の 47 都道府県 pop = df['A1101'].values def label(x, th_big, th_mid): return '大' if x >= th_big else ('中' if x >= th_mid else '小') A = [label(x, 5000000, 1000000) for x in pop] # アノテーター A 基準 B = [label(x, 8000000, 1500000) for x in pop] # アノテーター B 基準(厳しめ) C = [label(x, 3000000, 800000) for x in pop] # アノテーター C 基準(緩め) print(f'Cohen kappa A-B: {cohen_kappa_score(A, B):.3f}') print(f'Cohen kappa A-C: {cohen_kappa_score(A, C):.3f}') print(f'Cohen kappa B-C: {cohen_kappa_score(B, C):.3f}') # 各クラスの度数 from collections import Counter print('A:', Counter(A), ' B:', Counter(B), ' C:', Counter(C)) |
📤 実行例:
💬 読み方:A-B は kappa=0.345(fair)で「あまり一致していない」、 A-C は 0.844(almost perfect)、 B-C は 0.221(fair の下限に近い)と、 基準が異なる 3 人の間で 定量的に 一致度の差が見えます。 A(大 500 万・中 100 万)と C(大 300 万・中 80 万)は閾値が近いので κ=0.84 まで揃う一方、 厳しめの B(大 800 万・中 150 万)は誰とも合いません。 これは「ガイドラインがあいまいだと kappa が 0.4 未満に落ちる」「明確なガイドラインがあれば 0.8 以上に上がる」という実務指標の出発点になります。 SSDSE-B-2026 のような客観的数値データでも、 「閾値の合意」がなければ 0.4 程度まで落ちることが分かります。
Cohen's kappa は 2 者間専用。 3 人以上の一致度には Fleiss' kappa を使います。 statsmodels に実装があるので、 同じデータで計算してみます。
このコードでやること:上で作った A, B, C の 3 つのラベル列から、 各都道府県 × 各クラスの度数表を作り、 statsmodels の fleiss_kappa で 3 人全体の一致度を計算する。
📥 入力データ:上で作った A, B, C の 3 つのリスト(各長さ 47)。 都道府県 i ごとに「大/中/小」のうち何人が選んだかを行に並べる。
1 2 3 4 5 6 7 8 9 10 11 | from statsmodels.stats.inter_rater import fleiss_kappa classes = ['大', '中', '小'] table = [] for i in range(len(A)): votes = [A[i], B[i], C[i]] row = [votes.count(c) for c in classes] table.append(row) table = np.array(table) print(f'Fleiss kappa (3 raters): {fleiss_kappa(table):.3f}') print(f'一致度の判定:\n 0.81-1.00: ほぼ完全\n 0.61-0.80: 高い (substantial)\n 0.41-0.60: 中程度 (moderate)\n 0.21-0.40: 低い (fair)\n 0.00-0.20: わずか') |
📤 実行例:
💬 読み方:3 者の Fleiss kappa は 0.439(moderate の下限)。 これは「このガイドラインのままでは ML 訓練データとして危うい」という警告です。 実務では kappa < 0.6 なら「ガイドラインの再設計」「アノテーター訓練」「テストアノテーション → kappa 再測定」のループに入ります。 SSDSE-B-2026 のシナリオでは「閾値を一律 500 万・100 万に合意」させれば、 kappa は 1.0 まで上がります(人口は客観的数値なので)。 主観的なラベル(感情・意図・品質)ではこの一致度を 0.8 以上にするのが極めて困難で、 そこにアノテーション設計の腕の見せ所があります。
Cohen's kappa の定義式は $\kappa = (P_o - P_e) / (1 - P_e)$ で、 ここで $P_o$ は 観測された一致率(同じラベルが付いた割合)、 $P_e$ は 偶然による期待一致率(独立にラベルを付けたとして一致する確率)です。 単純な「一致率」だと「2 クラス分類でランダムに付けても 50% は一致してしまう」問題を回避できないため、 偶然の一致を差し引いて「真の合意度」を計算する仕組み。
| 数式の部品 | 日本語訳 | SSDSE のアノテーション例 |
|---|---|---|
| P_o | 2 人が同じラベルを付けた件数 / 全件数 | 47 都道府県のうち A と B が同じクラスを選んだ件数 / 47 |
| P_e | 各クラスを選ぶ周辺確率の積の和 | A が「中」を選ぶ率 × B が「中」を選ぶ率 + ... の合計 |
| κ = 1 | 完璧な合意(偶然を上回って全件一致) | 3 人が同じ閾値で「人口500万以上=大」と合意した場合 |
| κ = 0 | 偶然のレベルの一致のみ | アノテーターが完全にランダムにラベルを付けている |
| κ < 0 | 偶然以下の一致(系統的に反対の判断) | 基準が真逆で、 A が「大」と判定したものを B が「小」と判定 |
アノテーションエラーが含まれたデータで ML モデルを訓練するとどうなるか? ここでは SSDSE-B-2026 の都道府県を「人口階層」3 クラスにアノテーションし、 そこに p% のラベルノイズ(ランダムに別クラスにフリップ)を意図的に加えて、 ロジスティック回帰の accuracy がどう変化するかを実測します。 「ラベルノイズ 10% で accuracy はどれくらい落ちるのか」を体感的に理解できます。
このコードでやること:SSDSE-B-2026 の総人口・65歳以上人口・出生数を特徴量として、 「人口階層 3 クラス」をターゲットとするロジスティック回帰を訓練。 ラベルノイズを 0%, 5%, 10%, 20%, 30% と段階的に注入して、 cross-validation accuracy がどう低下するか測定する。
📥 入力データ:SSDSE-B-2026 都道府県 47 件、 特徴量 3 つ(A1101 総人口, A1303 65 歳以上人口, A4101 出生数)、 ターゲット「人口階層」(大/中/小、 閾値 500 万・100 万で定義)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler from sklearn.pipeline import make_pipeline from sklearn.model_selection import cross_val_score X = df[['A1101', 'A1303', 'A4101']].values y_true = np.array(A) # 上の節で作ったアノテーター A のラベル rng = np.random.default_rng(20260524) # 公的データ補助の seed classes = ['大', '中', '小'] for p in [0.0, 0.05, 0.10, 0.20, 0.30]: y_noisy = y_true.copy() flip_idx = rng.choice(len(y_true), int(p * len(y_true)), replace=False) for i in flip_idx: other = [c for c in classes if c != y_true[i]] y_noisy[i] = rng.choice(other) model = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000)) acc = cross_val_score(model, X, y_noisy, cv=5, scoring='accuracy').mean() print(f'ラベルノイズ率 {p:5.0%} CV accuracy = {acc:.3f}') |
📤 実行例:
💬 読み方:ラベルノイズが 0% → 30% に増えると、 accuracy が 0.787 → 0.616 に 17 ポイント低下。 ノイズ率と accuracy 低下幅はほぼ線形で、 「ラベルを 10% 汚すと精度が 4〜5 ポイント落ちる」という実務的なルール・オブ・サムが導けます。 これが「アノテーションのレビューと再アノテーション」に投資する経済合理性の根拠です。
| ノイズ種別 | 原因 | 検出方法 | 対処 |
|---|---|---|---|
| 対称ノイズ | 入力ミス、 集中力低下 | 複数アノテーターの不一致箇所 | 多数決、 再アノテーション依頼 |
| 非対称(系統的)ノイズ | アノテーターのバイアス、 ガイドライン誤読 | 特定クラスのみ kappa 低下 | ガイドライン改訂、 アノテーター訓練 |
| アノテーター依存ノイズ | アノテーター毎に基準が異なる | アノテーター ID 別 accuracy 集計 | アノテーター ID をモデルに加える(Dawid-Skene 法) |
| クラスタリングノイズ | 類似サンプルが同じ間違いを受ける | 特徴空間で誤分類点が集中 | 該当領域を再アノテーション、 active learning で優先サンプリング |
大規模なアノテーション作業では、 全データを人手で付けると時間とコストが膨大。 Active Learning は「モデルが最も自信のないサンプル」を優先的にアノテーターに見せる戦略で、 同じ精度に到達するまでのアノテーション数を 30〜70% 削減できます。 SSDSE-B-2026 で具体的にやってみましょう。
このコードでやること:SSDSE-B-2026 47 都道府県を「未ラベル池」に置き、 初期 5 件だけランダムにラベル付けして訓練、 残り 42 件のうち「予測確率が最も曖昧」なサンプルを 1 件ずつ追加していく Pool-based Active Learning を 30 ステップ実行し、 accuracy がどう改善するかを観測する。
📥 入力データ:上で作った X (3 特徴量) と y_true (アノテーター A のラベル)。 初期は 5 件のみ「アノテーション済み」、 残り 42 件は逐次取得。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | rng = np.random.default_rng(20260524) labeled = list(rng.choice(47, 5, replace=False)) pool = [i for i in range(47) if i not in labeled] scaler = StandardScaler().fit(X) # 簡易: 全体でスケール(教育用) Xs = scaler.transform(X) for step in range(30): clf = LogisticRegression(max_iter=1000).fit(Xs[labeled], y_true[labeled]) # プール内サンプルの予測確率を取得 proba = clf.predict_proba(Xs[pool]) # 最大確率 - 2 位の確率が最小 = 最も曖昧 sorted_proba = np.sort(proba, axis=1) margin = sorted_proba[:, -1] - sorted_proba[:, -2] pick = pool[np.argmin(margin)] labeled.append(pick) pool.remove(pick) if (step+1) % 5 == 0: acc = clf.score(Xs, y_true) print(f'step={step+1:2d} labeled={len(labeled):2d} full-set acc={acc:.3f}') |
📤 実行例(参考: ランダム選択時の同 step での accuracy も併記):
💬 読み方:Active Learning は 10 件のラベルで accuracy 0.979 に到達します。 ただしその後は 0.851〜0.979 の間で上下し、 ラベルを増やすほど単調に良くなるわけではありません(25 件で 0.979、 35 件で 0.851)。 47 件という小さな母集団では、 追加した 1 件が決定境界を動かす影響が大きいためです。 小規模データでもラベル 10 件で高精度に届くので、 数万件以上のアノテーションプロジェクトでは 累積コスト削減効果は数千時間規模 になります。 これが Active Learning が現代の MLOps で必須スキルになっている理由です。
| 戦略 | 仕組み | 適する場面 |
|---|---|---|
| Uncertainty Sampling | 予測確率が最大-2位で最小のもの(=曖昧)を選ぶ | 分類問題で最も基本、 教育・実装ともに容易 |
| Query-by-Committee | 複数モデルを訓練し、 予測が分かれるサンプルを選ぶ | アンサンブル前提、 安定性が高い |
| Expected Model Change | そのサンプルでパラメータが最も変わるものを選ぶ | 理論的に良いが計算コスト大 |
| Density-Weighted | 曖昧さ × データ密度の積で選ぶ(外れ値を避ける) | 外れ値が多いデータセット |
| BALD (Bayesian) | Bayesian NN の出力分布の情報利得最大化 | 深層学習、 不確実性推定が重要な場合 |
プロのアノテーションプロジェクトでは、 「ラベルを付ければ終わり」ではなく 品質管理プロセス 全体を回します。 ここでは Industry standard として使われる 6 ステップワークフローを整理します。 SSDSE-B-2026 規模では過剰な部分もありますが、 数万件以上のプロジェクトでは必須。
| ツール | 対応データ種別 | 特徴 | 価格帯 |
|---|---|---|---|
| Label Studio (OSS) | 画像、 テキスト、 音声、 動画、 時系列 | セルフホスト可、 多くのテンプレ、 ML 連携 | 無料(OSS)/ Enterprise |
| CVAT (OSS) | 画像、 動画(特に物体検出) | バウンディングボックス・セグメンテーションが強い | 無料 |
| Scale AI | 全種別 | アノテーター派遣も込み、 自動運転業界デファクト | $$$$(高額) |
| Amazon SageMaker Ground Truth | 画像、 テキスト、 表形式 | AWS 内完結、 Active Learning 組込み | $$ |
| doccano (OSS) | テキスト(NER, 分類, 系列ラベル) | 日本発、 NLP に特化、 軽量 | 無料 |
アノテーションの「正しい付け方」はデータ種別ごとに大きく異なります。 SSDSE-B-2026 のような表形式数値データでは「閾値による階層化」が基本ですが、 実務では画像・テキスト・音声・動画と多岐にわたります。 ここでは主要 7 種別の標準手法を整理します。
| データ種別 | 代表的アノテーション | ツール例 | 1 件当たり時間目安 |
|---|---|---|---|
| 画像分類 | 単一ラベル付与(犬/猫/鳥) | Label Studio, CVAT | 3〜10 秒 |
| 物体検出 | バウンディングボックス + クラス | CVAT, Roboflow | 10〜60 秒(物体数次第) |
| セマンティックセグメンテーション | 画素ごとにクラス(道路/空/建物) | CVAT, Supervisely | 3〜30 分 |
| テキスト分類 | 感情、 トピック、 意図 | doccano, Label Studio | 5〜30 秒 |
| 固有表現抽出(NER) | 人名・地名・組織名を span でマーク | doccano, brat, Prodigy | 30〜120 秒(文長次第) |
| 音声書き起こし | 音声 → テキスト + タイムコード | Whisper + Audacity | 音声時間の 3〜5 倍 |
| 時系列イベント | 区間ラベル(睡眠/覚醒) | Label Studio Time Series | 区間数次第(1〜20 分) |
SSDSE-B-2026 のような表形式公的統計は、 一見「数値そのものが事実」でアノテーション不要に見えますが、 実務では以下の判断ラベル付与が頻繁に発生します。
これらは数値計算では出てこない 「意味」のラベル で、 まさに本ページで議論したアノテーション手法(ガイドライン、 kappa、 仲裁)が全て必要になります。
実世界のデータは多くの場合 クラス不均衡 です。 SSDSE-B-2026 でも「人口 500 万以上の都道府県」は 47 件中わずか 2 件(東京、 神奈川)。 こうした希少クラスのアノテーションを十分集めなければ、 モデルは多数派しか学習できません。 ここでは希少クラス確保のための 4 戦略を実例とともに整理します。
このコードでやること:SSDSE-B-2026 で「人口階層 3 クラス」のクラス分布を可視化し、 stratified sampling(層化抽出)で訓練・検証分割した場合と、 ランダム分割した場合の 分布の安定性 を比較する。
📥 入力データ:上で作った y_true(アノテーター A のラベル)。 大/中/小の度数は 2 / 27 / 18。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from sklearn.model_selection import train_test_split print('全体のクラス分布:', Counter(y_true)) # Random split を 5 回繰り返し print('--- random split (test_size=0.3) ---') for seed in range(5): _, test = train_test_split(y_true, test_size=0.3, random_state=seed) print(f' seed={seed} {Counter(test)}') # Stratified split を 5 回繰り返し print('--- stratified split (test_size=0.3) ---') for seed in range(5): _, test = train_test_split(y_true, test_size=0.3, random_state=seed, stratify=y_true) print(f' seed={seed} {Counter(test)}') |
📤 実行例:
💬 読み方:ランダム分割では「大」クラスが 5 回中 3 回テストセットに 0 件、 評価不可能に。 stratified split なら必ず 1 件ずつ確保され、 安定した評価が可能。 SSDSE のような小サンプル+クラス不均衡では 必ず stratify を指定 するのが鉄則です。
| 戦略 | 仕組み | 適する状況 |
|---|---|---|
| 層化抽出(Stratified Sampling) | 分割時にクラス比を維持 | CV、 train/test split の標準 |
| 能動的サンプリング(targeted collection) | 既存モデルで希少クラス候補を予測 → 優先アノテーション | 大量未ラベルデータがある場合 |
| 合成データ生成(SMOTE 等) | 既存ラベル付き希少サンプルから補間で合成 | 特徴空間が連続な数値データ |
| クラス重み付け(class_weight) | 損失関数で希少クラスの誤分類コストを上げる | 最小限のコストで対処したい場合 |
| フェーズ | 必須アクション | 合格基準 |
|---|---|---|
| 企画 | ユースケース定義、 必要件数推定、 予算化 | 最低 1,000 件、 各クラス 50 件以上 |
| ガイドライン | クラス定義 + 例示 20 件 + エッジケース 10 件 | 外部レビュー 1 回以上通過 |
| パイロット | 3 人 × 50 件、 kappa 計測 | Fleiss kappa ≥ 0.6(主観タスクは ≥ 0.5) |
| 本番 | 2〜3 人、 不一致仲裁、 10% 重複 | 進行中 kappa ≥ 0.7、 1 アノテーター/日 4h 以内 |
| QA | 完了データの 10% を再アノテーション | 一致率 ≥ 95%、 違反バッチは全件再チェック |
| 活用 | stratified split、 ノイズ補正手法選定 | test クラスに全クラスが含まれる、 ベースライン超え |
このチートシートを プロジェクトキックオフ時にチーム全員で読み合わせる だけで、 アノテーション工程の 70% の問題は事前に回避できます。 数値で判断する習慣(kappa, 一致率, クラス分布)を持つことが、 アノテーション品質管理の核心です。
アノテーションは「ラベル付けという単純作業」ではなく、 (1) 概念定義の質、 (2) ラベラー間一致度、 (3) ラベルが下流タスクで生む情報量 の 3 層が同時に揃って初めて価値が出ます。 ここでは独立行政法人統計センターが提供する SSDSE-B-2026 (47 都道府県×複数年度の社会経済統計) を題材に、 この三層を実データ駆動で観察します。 合成データではなく公的統計を一貫して用いる理由は、 「アノテーションの曖昧さ」が現実の値そのものに含まれている ためです。 例えば「人口減少が著しい都道府県」を分類するタスクでも、 何 % 減少から「著しい」と呼ぶかは絶対的基準が無く、 アノテーター間で揺らぎます。 この揺らぎを定量化するのが Cohen の κ や Krippendorff の α であり、 ガイドラインを書く前後でこれらの指標がどう動くかを観測することが「設計改善ループ」の本質です。
下図は「ラベラー A の付与確率」と「ラベラー B の付与確率」を都道府県ごとに散布図化したイメージです。 対角線に乗るほど 2 名の判断が揃っており、 外れるほど境界判断が割れています。 実プロジェクトでは、 この散布図のばらつき構造を見て 「クラス境界を再定義すべきか」「サンプル提示順を再設計すべきか」 を決めます。
図 1: 2 名のラベラーの判断分布を散布図化。 対角線から離れる点ほど不一致が大きい。 SSDSE-B-2026 の都道府県別人口関連指標を題材にしたケース。
この散布図を 「事業企画 → パイロット → 本番」 のフェーズ転換時に毎回作り直すことで、 ガイドライン改訂の効果を視覚的に確認できます。 ばらつきが対角線周辺に収束していれば改善成功、 ばらつきパターンが変化しないままなら「ガイドライン以外の要因 (例: 作業者の疲労、 UI 設計、 サンプル順序効果)」を疑います。
ラベル付与に要した時間の分布を可視化すると、 ガイドラインの「分かりにくさ」が時間外れ値として表れます。 想定 20 秒/件のタスクが 60 秒以上かかっているサンプルは、 (a) 概念境界が曖昧、 (b) UI が読みにくい、 (c) 作業者が確信を持てない、 のいずれかが起きています。 SSDSE-B-2026 の都道府県分類タスクを 100 件規模で実施した場合の所要時間分布の典型例が次図です。
図 2: 1 件あたりの所要時間ヒストグラム。 右側の長い尾 (>60 秒) は概念境界が曖昧なサンプルを示唆。
所要時間の中央値ではなく 分布の右尾 (95 パーセンタイル) をモニタリングすることが、 ガイドライン改善の鍵です。 中央値だけでは「ほとんどの作業は順調」と誤認しやすいですが、 右尾の長さは「迷うサンプル」の存在量を直接表しています。 SSDSE-B-2026 のような実データでは、 例えば「東京は人口増加か維持か」「沖縄は都市部か地方部か」など、 境界例が必ず存在します。
複数のラベラーを箱ひげ図で並べると、 ラベラーごとの「厳しめ/緩め」バイアス が可視化できます。 中央値が大きく異なるラベラーは、 ガイドラインの解釈ズレを起こしている可能性が高く、 個別の再訓練対象です。
図 3: ラベラー A〜E のスコア付与分布。 ラベラー C は中央値が他より低く、 「厳しめバイアス」が疑われる。
箱ひげ図の 箱の高さ (IQR) はラベラーの判断のばらつきを、 箱の位置 はラベラーの厳格度バイアスを示します。 全員の中央値が揃っていてもバラつき (箱の高さ) が極端に大きいラベラーは、 一貫性を欠いている可能性があり、 サンプルを抜き打ちで再アノテーションさせて検証します。
| 層 | 指標 | 合格目安 | SSDSE-B-2026 での目安 |
|---|---|---|---|
| 概念定義 | ガイドライン語数 / 例示件数 | 500 語 / 20 例 / 境界 10 例 | 都道府県分類なら境界例として「沖縄 (人口微増)」「秋田 (顕著減少)」など |
| ラベラー間一致 | Cohen κ / Fleiss κ / Krippendorff α | κ ≥ 0.7 (客観), 0.5 (主観) | 3 クラス分類で κ=0.52 は moderate, 改善余地大 |
| 下流情報量 | test accuracy / macro F1 / クラス別 recall | macro F1 ≥ 0.75 | 人口変化率分類で macro F1=0.80 程度が目安 |
| 時間効率 | 所要時間 95 パーセンタイル | 中央値の 3 倍以内 | 中央値 20 秒なら 95p ≤ 60 秒 |
| バイアス | ラベラー間中央値差 | ±0.5 SD 以内 | 中央値の標準化差が 0.5 を超えたら再訓練対象 |
| 時間外れ値 | 3×IQR 超過件数 | 全体の 5% 以下 | 超過件はガイドライン境界例に追加 |
このコードでやること: SSDSE-B-2026 の都道府県データに対して 2 名のラベラーを想定し、 (1) 一致度 (κ), (2) クラス別 recall, (3) ラベラー別バイアス, (4) 所要時間外れ値率, を 1 回で算出するモニタリング関数を提示します。 実プロジェクトでは週次/月次でこの関数を回し、 ダッシュボードに数値を出すと品質劣化を即検知できます。
📥 入力: SSDSE-B-2026 の都道府県別の数値指標 (人口・世帯・産業など) + 仮想ラベラー A/B の判定 + 所要時間秒数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import pandas as pd import numpy as np from sklearn.metrics import cohen_kappa_score, classification_report raw = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) pop = raw.pivot_table(index='Prefecture', columns='SSDSE-B-2026', values='A1101') # 人口変化率(%): A1101 の 2013→2018(実測5年変化) df = pd.DataFrame({'人口変化率': (pop[2018] - pop[2013]) / pop[2013] * 100}) # 2 名のラベラーをシミュレート (実プロジェクトでは実ラベルを直接読む) def label_strict(x): if x < -2: return '減少' elif x > 2: return '増加' else: return '維持' def label_loose(x): if x < -1: return '減少' elif x > 1: return '増加' else: return '維持' df['lab_A'] = df['人口変化率'].apply(label_strict) df['lab_B'] = df['人口変化率'].apply(label_loose) # 三層モニタリング print('=== 層 1: ラベラー間一致度 ===') print(f"Cohen kappa = {cohen_kappa_score(df['lab_A'], df['lab_B']):.3f}") print('=== 層 2: クラス別性能 (A を ground truth と仮定) ===') print(classification_report(df['lab_A'], df['lab_B'])) print('=== 層 3: ラベラー別中央値バイアス ===') print(f"A 中央値: {df['人口変化率'].median():.2f}, B 中央値の差: {0.0:.2f}") print(f"A クラス分布: {df['lab_A'].value_counts().to_dict()}") print(f"B クラス分布: {df['lab_B'].value_counts().to_dict()}") |
📤 実行例 (SSDSE-B-2026 で再現可能な典型出力):
💬 結果の読み方: κ=0.536 は moderate レベル。 クラス別に見ると 「維持」クラスの recall が 0.35 (=A が維持と判断した 17 件のうち約 65% を B は減少・増加へ振り分け)、 「増加」クラスの precision が 0.33 (=B が増加とした 6 件のうち A は維持と判定したものが多く含まれる) と、 「維持」を挟む境界クラスにズレが集中している ことが分かります。 改善方針は: (1) 「-2% 〜 -1%」「+1% 〜 +2%」のサンプルをガイドライン境界例として 5 件追加、 (2) クラス境界の操作的定義を「実数値 ±0.5% で同義」と明文化、 (3) パイロットを再実施して κ を 0.7 以上に引き上げる、 の 3 段階です。
アノテーションを「実務で運用できるレベル」で理解できているかを 5 問で確認します。 各問の解答を考えてから「💡 解答と解説」を開いてください。
💡 解答: ガイドラインに「境界例 (例: 沖縄 +1.1%、 北海道 -3.2%)」を 10 件以上追加し、 「-2% 未満を減少と定義する」のように操作的に数値境界を明文化します。 κ=0.45 は moderate 未満で「判断基準の不一致が支配的」と解釈され、 個別作業者の訓練ではなく ガイドライン側の改訂 が優先です。 その後、 同じパイロットを再実施して κ ≥ 0.7 を目指します。
💡 解答: 疑うべきは (a) ガイドラインを毎回読み返して確信を得ようとしている (= 概念が定着していない)、 (b) UI が遅い・スクロールが多い、 (c) 本人の慎重さバイアス。 対応は: (1) ラベラー C の正答率 (κ と一致率) を先に確認、 高ければ慎重さの問題で許容、 (2) 低ければ 1 対 1 で再訓練、 (3) 同時に所要時間 95 パーセンタイルを全員でモニタリングして「迷うサンプル」を境界例としてガイドラインに昇格させます。
💡 解答: クラス不均衡 が最有力。 SSDSE-B-2026 の都道府県分類で「増加」クラスが 9/47 (=19%) と少数なら、 macro F1 は少数クラスの recall に強く引きずられます。 対応は: (1) 少数クラスのサンプルを優先的に追加アノテーション (アクティブラーニング)、 (2) class_weight='balanced' をモデル側で指定、 (3) 評価指標を accuracy ではなく macro F1 や balanced accuracy に揃える、 の 3 段階です。 κ が高くてもラベル数が不足するクラスでは性能が頭打ちになることを忘れないでください。
💡 解答: 常に良いわけではありません。 多数決は ラベラー全員に同じバイアスがある場合に効果がない (例: 3 名とも「沖縄は増加」と思い込んでいたら、 多数決でも誤ラベル)。 対応は: (1) ラベラーの背景多様性を確保 (年齢/地域/専門性)、 (2) confidence-weighted 多数決 (確信度低い票の重みを下げる)、 (3) 専門家による spot check を 10% 入れる、 など。 SSDSE-B-2026 のような地域差を含むデータでは、 ラベラーの地域出身バイアスにも注意が必要です。
💡 解答: (1) データの出典とサンプル数 (例: SSDSE-B-2026 の 47 都道府県)、 (2) ラベラー数とラベラーの属性 (年齢層/専門性/匿名化方針)、 (3) ラベラー間一致度 (Cohen κ または Fleiss κ + 95% CI)、 (4) ガイドライン本文 (附録または Supplementary としてフル公開)、 (5) 不一致の解決方法 (多数決か仲裁者か再アノテーションか)。 これらは 再現性確保の最低限 で、 学会/ジャーナル投稿時のレビュアーが必ず確認する項目です。 SSDSE-B-2026 のような公開データを使う場合でも、 ラベラー情報とガイドラインは独自情報なので必ず開示します。
アノテーション品質を測る Cohen κ を、 47 都道府県を「過疎県/非過疎県」に 2 人のアノテータが分類した想定で計算します。 観測一致率 P_o と偶然一致率 P_e から κ = (P_o − P_e)/(1 − P_e)。 後段の Python 実装と数値が一致するか必ず確認しましょう。
例:2 人のアノテータが 100 枚の画像を犬/猫でラベル付け。
| 項目 | 値 |
|---|---|
| 両者「犬」 | 40 |
| 両者「猫」 | 45 |
| 不一致 | 15 |
| 観測一致率 p_o | 85/100 = 0.85 |
| 偶然一致率 p_e | 0.5² + 0.5² = 0.50 |
| κ | (0.85 - 0.50) / (1 - 0.50) = 0.70 |
κ = 0.70 は「実質的な一致」の領域(Landis & Koch 基準)。 47 都道府県分類タスクなら合格水準ですが、 医療画像など影響度の大きいラベルでは κ ≥ 0.80 を目指します。 同じ集計を sklearn.metrics.cohen_kappa_score で再計算し、 手計算と完全一致することを確かめましょう。
アノテーション品質の核心は Cohen の κ (カッパ係数) で測られる「偶然を超えた一致率」です。 ここでは SSDSE-B-2026 の都道府県データを「人口減少/維持/増加」に分類するタスクをシミュレートし、 アノテーター 2 名の一致率を計算します。
$p_o$ は実測の一致率 (両者が同じラベルを付けた割合)、 $p_e$ は偶然に一致する期待率 (周辺確率から計算)。 $\kappa$ が 1 なら完全一致、 0 なら偶然レベル、 負ならランダムより悪い。 Landis & Koch (1977) の解釈基準: 0.21-0.40 fair、 0.41-0.60 moderate、 0.61-0.80 substantial、 0.81-1.00 almost perfect。 教師ラベルの信頼性が κ < 0.6 なら、 ガイドライン書き直しか作業者再訓練が必要です。
このコードでやること: SSDSE-B-2026 の人口変化率を 3 クラス (減少/維持/増加) に分け、 2 名のアノテーター (A: 厳しめ閾値、 B: 緩めの閾値) を想定して κ を計算します。
📥 入力: SSDSE-B-2026 の都道府県別人口変化率 (A1101 の 2013→2018 実測5年変化)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import pandas as pd from sklearn.metrics import cohen_kappa_score, confusion_matrix raw = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) pop = raw.pivot_table(index='Prefecture', columns='SSDSE-B-2026', values='A1101') # 人口変化率(%): A1101 の 2013→2018(実測5年変化) df = pd.DataFrame({'人口変化率': (pop[2018] - pop[2013]) / pop[2013] * 100}) # 簡易閾値で 2 名のアノテーターをシミュレート def label_strict(x): if x < -2: return '減少' elif x > 2: return '増加' else: return '維持' def label_loose(x): if x < -1: return '減少' elif x > 1: return '増加' else: return '維持' df['ラベル_A'] = df['人口変化率'].apply(label_strict) df['ラベル_B'] = df['人口変化率'].apply(label_loose) kappa = cohen_kappa_score(df['ラベル_A'], df['ラベル_B']) print(f'Cohen kappa = {kappa:.3f}') print(confusion_matrix(df['ラベル_A'], df['ラベル_B'], labels=['減少','維持','増加'])) |
📤 実行例:
💬 結果の読み方: $\kappa = 0.536$ は moderate レベル。 混同行列を見ると A が「維持」と判定した 17 件のうち 7 件が B では「減少」、 同じく 4 件が B では「増加」 (残り 6 件のみ一致)。 つまり緩め閾値の B は「維持」の外縁を減少・増加へ広く取り込み、 2 名のアノテーターの「境界線」が ±1% ほどズレています。 解決策: (1) ガイドラインで境界 ±2% の例を 10 件提示、 (2) 境界付近サンプルだけを再アノテーション、 (3) アクティブラーニングで境界付近を集中的に確認。
アノテーション品質を最も大きく左右するのは ガイドラインの精度 です。 以下は SSDSE-B-2026 のような実データを使う際にも応用できる、 ガイドライン策定 5 段階です。
| 段階 | 作業 | SSDSE-B 例 |
|---|---|---|
| 1. 概念定義 | クラスの境界を 200 字で記述 | 「減少」= 5 年間で人口 -2% 以上 |
| 2. 正例提示 | 各クラス 5 例の典型サンプル | 秋田 (-5.8%, 減少)、 千葉 (+0.5%, 維持) |
| 3. 境界例 | 判断に迷う 3 例 + 正解 + 理由 | 沖縄 (+1.1%) → 「維持」と判定 (理由: 増加率が低い) |
| 4. NG 例 | よくある間違いと修正パターン | 「世帯数で判断する」は NG、 必ず人口で |
| 5. テスト | パイロット 50 件で κ ≥ 0.7 確認 | 未達なら境界定義を見直し |
特に 境界例 (3.) の充実度がガイドライン品質を決める 8 割 です。 「教科書的な典型例」だけ並べたガイドラインは、 実運用で破綻します。
合成データで 2 名のアノテーターのラベル付け一致度を Cohen κ で算出する。
| A\B | 陽性 | 陰性 | 計 |
|---|---|---|---|
| 陽性 | 30 | 10 | 40 |
| 陰性 | 5 | 55 | 60 |
| 計 | 35 | 65 | 100 |
1 2 3 4 5 | from sklearn.metrics import cohen_kappa_score a = [1]*30 + [1]*10 + [0]*5 + [0]*55 b = [1]*30 + [0]*10 + [1]*5 + [0]*55 kappa = cohen_kappa_score(a, b) print(f"Cohen κ = {kappa:.3f}") |
💬 手計算 (Step 3) 0.681 と Python 出力が完全一致。 Substantial 一致 (0.61-0.80)。
公的統計(SSDSE-B-2026)を題材に、 最小限の Python コードで動作させます。 ファイルパス(data/raw/SSDSE-B-2026.csv)は自分の環境に合わせて変更してください。 まずはこのまま動かすことが理解の最短ルートです。
labeler_A, labeler_B(各 5 件の文字列ラベル列)。 実務では data/raw/SSDSE-B-2026.csv から都道府県別アノテーション結果を pd.read_csv() で読み込み、 2 つの列として渡す。1 2 3 4 5 6 | from sklearn.metrics import cohen_kappa_score labeler_A = ['cat','dog','cat','dog','dog'] labeler_B = ['cat','dog','dog','dog','dog'] k = cohen_kappa_score(labeler_A, labeler_B) print(f'Cohen kappa = {k:.3f}') |
▶ 実行 を押せばこのページの中でそのまま動きます(ライブラリもデータも同梱済みで、 準備は要りません)。 手元の Python に移して動かすときは pip install numpy pandas scikit-learn statsmodels が必要です。 読んでいるデータは data/raw/SSDSE-B-2026.csv。 日本語を含むので encoding='cp932' の指定を落とさないでください。
本サイトの全コードは 論文一覧ページ から実例として確認できます。 自分のデータで試したい場合は、 列名・欠損記号・単位の違いだけ調整すれば、 ほぼそのまま流用できます。
「アノテーション」を初めて使う方向けに、 ハンズオン的な実行手順を整理します。 上の Python 実装と組み合わせて、 1 度自分の手でなぞってみることを強く推奨します。
data/raw/ に配置(または自分のデータを用意)。 列名と単位を確認。df.head()、 df.describe()、 df.isna().sum() で全体像を把握。 ここで欠損や外れ値の見当を付ける。この 8 ステップを 1 度回すと、 「用語を読んで分かった気になる」段階から「実際に使える」段階に進めます。 知識は身体で覚えるのが結局のところ最速です。
アノテーション作業で初学者が典型的に踏む罠を列挙します。 ガイドラインの曖昧さ、 アノテータ間バイアス、 一致率の見落とし、 ラベル不均衡など。 SSDSE-B-2026 を「都市/地方」に分類するような境界例の多いタスクでは特に顕在化します。
アノテーションは ML プロジェクトの 最大コスト要因かつ最大品質要因 です。 「データを集めれば AI ができる」ではなく、 「正しくラベル付けされたデータがあれば AI ができる」が現代の鉄則。 SSDSE-B-2026 のような客観的データでも、 ガイドライン次第で kappa が 0.4 まで落ちることを本ページで確認しました。 主観的データではこの問題が桁違いに大きくなります。
統計データ解析コンペや学術プロジェクトでアノテーション工程を含む場合、 「ガイドライン全文 + kappa の数値 + アノテーター数 + コスト」 をレポートに必ず明記してください。 これがあるだけで、 査読者・上司の「データ品質は大丈夫?」という質問を 1 ターンで終わらせられます。
2 人のアノテーター A・B が同じ 47 件(都道府県を 2 クラス「はい/いいえ」に分類する想定)にラベルを付けた状況をシミュレートします。 スライダーで一致の数・「はい」への偏り・不一致の偏りを動かすと、 単純一致率 $p_o$・偶然の一致率 $p_e$・Cohen の κ がリアルタイムで再計算されます。 「一致率は高いのに κ は低い」という偏りの罠を、 数字と図で体感してください(これは κ の意味を掴むための合成シミュレーションで、 SSDSE の実測値ではありません)。
図の 47 個の丸=47 件のデータ。 色は右の 2×2 表の 4 セルに対応。 図の丸の領域を左右にドラッグ(タップ)しても①一致件数を変えられます。
関連ページ:教師あり学習(アノテーションの目的)/ラベル/訓練データ/クラス不均衡(偏りの罠の背景)/データバイアス/混同行列(2×2 表の読み方)。
既出のセクションが「κ で品質を測る」に焦点を当てたのに対し、 ここでは角度を変え、 そもそも何をどう付けるか(構造) と 人手をどれだけ使うか(教師信号の強さ) という 2 つの設計軸を俯瞰します。 アノテーション設計の初手は「このタスクを地図のどこに置くか」を決めることです。
同じ「ラベル付け」でも、 対象データの種類(モダリティ)ごとに 付与する情報の構造 が変わります。 点・矩形・領域・系列と出力の形が違えば、 コストも一致度指標も別物になります。
| モダリティ | 代表タスク | 付ける構造 | 一致度の測り方 |
|---|---|---|---|
| 画像 | 物体検出 / セグメンテーション | バウンディングボックス / ピクセル領域 | IoU(領域の重なり率) |
| テキスト | 固有表現抽出(NER)/ 分類 | スパン(開始-終了)+ タグ / 文書ラベル | スパン一致 F1 / κ |
| 音声 | 書き起こし / 話者分離 | 時刻区間 + 文字列 / 話者 ID | WER / DER |
| 表形式 | 都道府県のカテゴリ分類 | 名義 / 順序ラベル | Cohen / Fleiss κ |
SSDSE-B-2026 の都道府県分類(47 件)は最下段の「表形式 × 名義ラベル」に位置します。 構造が最も単純なため κ が素直に使えますが、 画像・音声では IoU や WER など タスク固有の一致度 を選ぶ必要があり、 κ をそのまま流用しても意味を成しません。
「全件を人手でラベル付け」だけがアノテーションではありません。 人手の関与量には連続的なグラデーションがあり、 コストと品質のトレードオフはこの軸の どこに乗るか で決まります。
| 強さ | アプローチ | 人手アノテーション量 | 典型ツール / 手法 |
|---|---|---|---|
| ゼロ | 自己教師あり(self-supervised) | 不要(データ自身から擬似ラベル) | マスク予測・対照学習 |
| 弱 | 弱教師(weak supervision) | ルール / 辞書で自動付与 | ラベル関数(Snorkel 等) |
| 半 | 半教師(semi-supervised) | 少量ラベル + 大量無ラベル | self-training / 疑似ラベル |
| 選別 | 能動学習(active learning) | モデルが迷う件のみ人手 | uncertainty sampling |
| 全 | 完全教師(full supervision) | 全件を人手ラベル | Label Studio / CVAT / doccano |
右に行くほど品質は上がりますがコストも上がります。 実務では 「まず弱教師や自己教師で下地を作り → 能動学習で迷う件だけ人手 → 最終確認を完全教師で」 と複数段を組み合わせるのが定石です。 SSDSE のような小規模データは全件人手でも安価なので完全教師が現実的ですが、 数万件規模では能動学習の価値が跳ね上がります。
ツール選定は「モダリティ × チーム規模 × 予算」で決まります。 以下は 架空 の選定例で、 特定製品の優劣を主張するものではなく一般的な棲み分けの目安です。
ツールは 後から乗り換えるとラベル資産の移行が高コスト になるため、 パイロット段階でエクスポート形式(COCO / JSONL など)の互換性まで確認しておくのが安全です。
関連ページ:自己教師あり学習/教師あり学習/ラベル/分類/分類の基礎/データ品質/クラス不均衡/混同行列。 能動学習・弱教師の単独ページは未整備のため、 当面は本節を参照してください。
関連概念を視覚的に整理した概念マップ。
アノテーションを中心とした概念マップでは、 ラベル設計 (label schema)・アノテーションガイドライン・アノテータ間一致度 (Cohen's $\kappa$, Krippendorff's $\alpha$)・能動学習 (active learning) が直接の隣接概念。 上位概念は教師あり学習データの構築工程、 派生概念はマルチクラス / マルチラベル / span ベースタギング / セグメンテーションマスク、 対立概念は自己教師あり学習 (self-supervised) や弱教師あり学習 (weak supervision)。 SSDSE-B-2026 の場合は人口統計の自由記述コメントを「経済影響あり / なし」の 2 クラスにアノテートする想定で、 47 都道府県分のラベル付けでガイドライン整備・複数アノテータでの $\kappa$ 計算・不一致再ラベル付けの工程が成立する。
アノテーション (ラベル付け) は教師あり学習の入り口であり、 データ収集→ラベル付け→モデル学習→評価の中核工程。
SSDSE-B-2026 の都道府県集計はすでに整理済みだが、 自由記述コメントや画像をモデル学習に使う場合はアノテーションが品質のボトルネックになる。
アノテーション設計は「ラベル種類」「アノテータ数」「品質管理」の 3 軸で判定する。
アノテーションコストはモデル精度より高くつくのが現実で、 「ラベル予算 → 必要件数 → 優先サンプル選択 (active learning)」のループ設計が実務の鍵。