論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
公平性
Fairness
倫理
別称: AI公平性

🔖 キーワード索引

公平性fairnessバイアス差別Demographic ParityEqualized OddsAI倫理保護属性

fairness」は統計データ分析の文脈で扱う重要概念のひとつ。 本ページでは「fairness」を取り巻く中核キーワードを以下にチップで一覧化する。 各キーワードは関連する概念・手法・道具立てを含み、 文献検索や学習計画の起点になる。

fairness統計分析SSDSE-B-2026前提条件適用範囲落とし穴関連手法Python 実装検証方法

これらのキーワードは「fairness の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。

💡 30秒で分かる結論

🍰 まずはやさしく

公平性は、AIが差別をしないための基準です。

正しい判断ができているか測るために使います。

部活のメンバー選びで不公平がないか考えるときと同じです。

ここでは、公平性を測る方法や対策について読みます。

AIシステムが差別的でないことの基準

📍 あなたが今見ているもの

🍰 まずはやさしく

公平性は、社会のルールに関わる大切な考え方です。

AIによる差別を防ぎ、法律を守るために使います。

スマホの顔認証などで不当な差が出ないようにします。

ここでは、公平性を学ぶための全体の流れを読みます。

AI採用、 ローン審査、 顔認識 — 差別的判断が社会問題化。 EU AI Act では高リスクAIに公平性監査が義務化される方向。 倫理を超えて法令対応事項に。

本ページでは「fairness」を扱う。 統計データ分析コンペティション (2026) の教材で、 SSDSE-B-2026 (47 都道府県 × 複数年 × 100 超列) の実データを使った再現可能な学習を目指す。

「fairness」は統計・データサイエンスの体系における重要概念のひとつ。 本ページは「定義・直感・数式・実装・落とし穴・関連手法」の 6 視点で構成され、 各視点は独立して読めるが順序通り読むと体系的な理解が得られる。

🎨 直感で掴む

🍰 まずはやさしく

公平性には、いくつかの考え方があります。

どの基準が正しいかを判断するために使います。

テストの点数と合格率の関係を考えるときのような話です。

ここでは、公平性の種類と難しい点について読みます。

採用 AI を例にすると、 公平性には少なくとも 3 つの異なる定義があります:

  • Demographic Parity (人口統計的均等): 男女で採用率が同じ ($P(\hat{Y}=1|A=男) = P(\hat{Y}=1|A=女)$)
  • Equal Opportunity (機会均等): 男女で「本当に優秀な人の合格率 = 真陽性率 TPR」が同じ
  • Equalized Odds (オッズ均等): 男女で偽陽性率 FPR と偽陰性率 FNR がいずれも同じ
  • Calibration (較正): 「スコア 0.7」と予測された人の実際の正例率が男女で同じ

Chouldechova (2017) と Kleinberg et al. (2016) は、 基底率 (各群の真の正例率) が群間で違うとき これら全てを同時に満たすことは数学的に不可能 と証明しました (Impossibility Theorem)。 例えば SSDSE-B-2026 で「大都市 vs 地方」を保護属性として推定した場合、 大都市の方が機会が多ければ Demographic Parity と Calibration は両立しません。

つまり「何を公平とするか」自体が技術ではなく 価値判断・社会合意の問題で、 COMPAS 再犯予測ツール (ProPublica 2016) の論争はまさにこの選択を巡るものでした。 米国 EEOC の 4/5 ルール (採用率比 ≥ 0.8) と EU AI Act (2026 施行) の高リスク区分では、 適用する公平性定義が異なります。

身近な例え:奨学金の選考

大学奨学金を「成績」だけで選ぶ場合、 もし家庭環境で塾通いができる学生が有利なら、 結果として高所得家庭の合格率が高くなる。 これは Demographic Parity に違反する可能性がある。 一方、 「同じ成績の学生は出身家庭によらず同じ確率で合格」していれば Equal Opportunity は満たされる。 どちらを優先するか? もし君が奨学金委員会のメンバーなら、 「結果の平等」と「機会の平等」のどちらを重視するだろうか? この問いに技術だけでは答えられないことが、 公平性問題の核心だ。

SSDSE-B-2026 想定:地域格差で見る公平性指標

属性群大学進学率 (真値)AI推薦合格率True Positive Rate (機会均等)
東京都市部72%78%0.91
地方中核市58%61%0.88
山間部・離島41%32%0.71

この AI 推薦システムは TPR が地域で 0.71〜0.91 とばらつき、 Equal Opportunity 不成立。 さらに合格率も地域で 32〜78% で Demographic Parity 不成立。 どちらの不成立をどこまで許容するかは「教育政策の価値判断」であり、 純粋な数学的最適化では決められない。

公平性 4 種の使い分け早見

  • 採用・与信 (差別禁止) → Demographic Parity + 4/5 ルール
  • 医療検診 (見逃しコスト大) → Equal Opportunity (TPR 均等)
  • 司法 (再犯予測)Equalized Odds (FPR + FNR 均等)
  • 保険料率算定Calibration (リスク予測が群間で正確)

📐 定義/数式

🍰 まずはやさしく

公平性とは、数式で表した差別のなさと定義します。

AIの計算結果が平等かを確かめるために使います。

買い物での割引率が誰でも同じか調べるようなものです。

ここでは、公平性を表す数式やグラフについて読みます。

公平性Fairness):AIシステムが差別的でないことの基準

同義・関連語:AI公平性

【Demographic Parity】
$$ P(\hat{Y}=1 \mid A=a) = P(\hat{Y}=1 \mid A=b), \quad \forall a, b $$
保護属性 $A$(性別、 人種等)の値によらず、 予測ラベル $\hat{Y}=1$ の確率が等しい。

📐 公平性 × 精度の Pareto frontier

制約 eps を変えながら学習すると、 「公平性」「精度」「校正」が同時に最適化できない曲面が見えます。 これを Pareto frontier (パレートフロンティア) と呼びます。 組織は この曲面上のどの点を選ぶかを倫理判断として行います。

eps (DP 上限)DP 差精度TPR (大都市/地方)
制約なし0.5610.8511.000 / 0.561
0.200.1960.7870.833 / 0.683
0.100.0990.7660.667 / 0.683
0.050.0480.7450.500 / 0.683
0.010.0080.6810.333 / 0.341

💬 eps を厳しくすると DP 差は小さくなるが、 精度が低下し、 大都市群の TPR が下がる。 これは「大都市の優秀者にも漏れが出る」ことを意味し、 単純な「公平 = 正義」ではない複雑性が現れる。

🔬 記号・用語の読み解き

記号意味
$A$保護属性(性別、 人種、 年齢など)
$\hat{Y}$AIの予測ラベル
$Y$真のラベル
プロキシ保護属性と相関する変数(郵便番号と人種等)

🔬 詳細な解説(深掘り)

概念の本質

公平性(Fairness)は、 単に用語の定義を覚えるだけでは本当には理解できません。 なぜこの概念が生まれたのかどんな問題を解決するために導入されたのか類似の手法とどう違うのか — これらを意識することで、 初めて「使える知識」になります。

数式や Python コードはあくまで 道具。 道具の使い方を覚える前に、 その道具で何をしたいか(目的) を明確にすることが、 データサイエンス学習の鉄則です。

他の概念との関係

公平性は単独の指標ではなく、 統計的差別禁止 (disparate impact)、 アルゴリズムバイアス、 個別公平性 vs 集団公平性、 因果推論との接続といった概念ネットワークの中心に位置します。 関連用語を辿ると以下の構造が見えます:

実務で気をつけるポイント

理論を学ぶことと、 実務で使えることは別物です。 公的統計(SSDSE、 e-Stat 等)の実データで実装・実験することで、 教科書だけでは見えない罠 に気付けます。 たとえば:

これらは 公平性 に限った話ではなく、 データサイエンス全般に共通する作法です。 「落とし穴」セクションの内容と合わせて、 自分なりのチェックリストを作るとよいでしょう。

📊 評価・検証の視点

公平性 を使った分析の 正しさを担保する ためには、 以下の観点で検証するのが定番です。

確認する点公平性 で何を見るか
属性を消せば公平、 ではないプロキシ(郵便番号等)から保護属性が推測できる。
複数定義の取り違えDP と EO は両立しない(不可能性定理)。
精度との両立公平性制約で精度が落ちる場合あり。 トレードオフを開示。
「無バイアス」は不可能公平性は完全達成ではなく、 継続的監視が現実解。
再現性同じデータ・同じコードで同じ結果が出るか。このページの ▶ 実行ボタンで確かめられます

💼 業界別の使われ方

公平性 は分野横断で活躍する概念です。 業界別に見ると以下のような使われ方があります。

🏥 医療・ヘルスケア
疾病予測、 診断支援、 治療効果の評価、 公衆衛生指標の分析(高齢化率、 罹患率、 医療費等)
🏛️ 行政・公共政策
EBPM(エビデンスに基づく政策立案)、 地域経済分析、 RESAS/e-Stat の活用、 政策効果測定
🏪 マーケティング・小売
顧客分析、 需要予測、 価格弾力性、 RFM分析、 A/Bテスト、 LTV予測
🏭 製造・品質管理
品質管理、 故障予知、 異常検知、 生産最適化、 サプライチェーン分析
💰 金融・保険
信用スコア、 リスク評価、 不正検知、 アルゴリズムトレーディング、 保険料設定
🎓 教育・研究
教育効果の測定、 学習分析、 研究データ解析、 統計教育、 データサイエンス人材育成

📈 公的統計データ(SSDSE)での具体例

公平性 を実際のデータで学ぶときは、 SSDSE(教育用標準データセット、 総務省統計局)が便利です。

これらは 統計センターの SSDSE ページ から CSV で直接ダウンロードできます。 上の Python コード例で data/raw/SSDSE-B-2026.csv としているのが、 まさにこれです。

実データで動かすことで、 教科書の例題では見えない 実務的な気づき(欠損のパターン、 単位の混在、 都道府県名の表記揺れ等)が得られます。

🔧 よくあるトラブルと対処

🐍 Python コードが動かない
→ Python 3.10+ と必要ライブラリ(pandas、 numpy、 scikit-learn 等)がインストール済みか確認。 pip install pandas numpy scikit-learn matplotlib で揃います。
📁 CSVファイルが読み込めない
→ ファイルパスを確認。 文字コードが utf-8 ではなく shift_jiscp932 の場合がある(古い日本の公的統計に多い)。 encoding='cp932' を試してください。
📐 数式が表示されない
→ ページが KaTeX を読み込んでいるはずです。 ブラウザのキャッシュをクリアするか、 開発者ツールで JavaScript エラーを確認。
🔢 数値計算結果が教科書と違う
→ 不偏推定(n-1)と標本推定(n)の違い、 浮動小数点誤差、 ライブラリのデフォルト引数の違いなどが原因。 ドキュメントを確認。
📊 グラフが描画されない
→ Jupyter Notebook なら %matplotlib inline、 スクリプト実行なら plt.show() を忘れずに。 日本語フォントは matplotlib 用に別途設定(japanize-matplotlib 等)が必要。

🔬 数式を言葉で読み解く(4 要素構造・1200 字以上)

公平性の代表指標 Demographic Parity(人口統計的均等) を 4 要素で精密に読み解きます。

$$ P(\hat Y = 1 \mid A = a) = P(\hat Y = 1 \mid A = b), \quad \forall a, b \in \mathcal{A} $$

① 左辺 $P(\hat Y = 1 \mid A = a)$ — 「サブグループ $a$ での陽性率」

$\hat Y$ は モデル予測(融資承認= 1、 不承認= 0 など)。 $A$ は 保護属性(性別・人種・年齢・国籍)。 $P(\hat Y = 1 \mid A = a)$ はサブグループ $a$ の中で陽性予測が出る確率。 「女性の中で融資承認率は何%か」を測る量。 実務では性別・人種・年齢区分などをサブグループとして設定し、 サブグループ間で陽性率が等しくなることを要求する。

② 右辺 $= P(\hat Y = 1 \mid A = b)$ — 「他サブグループ $b$ での陽性率」

$b$ は別のサブグループ(男性、 白人、 若年層)。 右辺は同じ陽性予測の条件付き確率を $b$ 側で測ったもの。 「男性の中で融資承認率は何%か」。 左辺=右辺「サブグループに関わらず承認率が同じ」を意味する。 つまり結果(output)の均等性を要求する指標。 米 EEOC の Disparate Impact ルール(4/5 ルール)は緩い形の Demographic Parity と等価で、 「マイノリティの承認率/マジョリティの承認率 ≥ 0.8」を法的閾値とする。

③ 全称量化子 $\forall a, b \in \mathcal{A}$ — 「すべての組み合わせで成立」

$\forall a, b \in \mathcal{A}$ は 「任意の 2 つのサブグループの組み合わせ」で等式が成立することを要求。 $\mathcal{A}$ が 2 値(男女)なら 1 つの等式、 $|\mathcal{A}| = 5$(年齢層 5 区分)なら $\binom{5}{2} = 10$ 個の等式すべて成立を求める。 実務では完全な等式は不可能なので、 Demographic Parity Difference (DPD) $= \max_{a,b} |P(\hat Y=1|A=a) - P(\hat Y=1|A=b)|$ を 0.05〜 0.10 以下に抑えるという緩和を採る。

④ 制約と限界 — 「他指標との同時達成不可能性」

この指標には致命的な限界がある。 Chouldechova(2017)と Kleinberg ら(2017)が独立に示した 「Fairness Impossibility Theorem」 によれば、 Demographic Parity、 Equalized Odds、 Calibration の 3 つは、 base rate(クラス事前確率)がサブグループ間で異なるとき、 同時に満たすことは数学的に不可能。 たとえば男女で犯罪再犯率の base rate が異なれば、 Demographic Parity を満たすと Equalized Odds が破れる。 したがって 「どの公平性を優先するか」は技術的選択ではなく、 社会的・倫理的選択 となる。 ML エンジニアは「すべて満たします」と約束できない。 これがアルゴリズム公平性の本質的難しさ。

🔬 公平性の数式を言葉で読み解く: 完全版チートシート

10 種類の公平性メトリクスを「定義式 → 直感 → 採用場面」で並列に並べます。 これは fairlearn / AIF360 の機能対応表でもあります。

名称数式数式を言葉で読み解く
Statistical / Demographic Parity$P(\hat Y=1 | A=a) = P(\hat Y=1 | A=b)$予測の「1 が出る確率」が群で等しい
Disparate Impact$P(\hat Y=1|A=u)/P(\hat Y=1|A=p) \geq 0.8$不利群比率 / 有利群比率 が 0.8 以上
Equal Opportunity$P(\hat Y=1 | Y=1, A=a) = P(\hat Y=1 | Y=1, A=b)$本来 1 の人を 1 と予測する率が群で等しい (= TPR 等価)
Equalized Odds$P(\hat Y=1 | Y=y, A=a) = P(\hat Y=1 | Y=y, A=b),\ y \in \{0,1\}$TPR も FPR も両群で等しい (より厳しい条件)
Predictive Parity$P(Y=1 | \hat Y=1, A=a) = P(Y=1 | \hat Y=1, A=b)$1 と予測した中での真陽性率 (Precision) が群で等しい
Calibration$P(Y=1 | \hat p = p, A=a) = p$「予測確率 p」と「実際の真陽率」が一致 (群で)
Treatment Equality$\mathrm{FN}/\mathrm{FP}$ が群で等しい偽陰性 / 偽陽性 の比率が群で等しい
Counterfactual Fairness$P(\hat Y_{A \leftarrow a} = 1 | X, A) = P(\hat Y_{A \leftarrow b} = 1 | X, A)$保護属性だけ書き換えた仮想世界での予測が変わらない
Individual Fairness (Lipschitz)$d_Y(M(x_1), M(x_2)) \leq L \cdot d_X(x_1, x_2)$似た個人には似た予測 (距離が L 倍以下)
Theil Index (不平等)$T = \frac{1}{N}\sum_i \frac{b_i}{\mu} \ln\frac{b_i}{\mu}$利得 $b_i$ の不平等度合いをエントロピー風に測る

💬 運用上の選び方: ① 採用・融資 → Equal Opportunity (本来資格のある人を漏らさない) ② 刑事司法 → Equalized Odds (両エラーを均等に) ③ 医療診断 → Calibration (予測確率の信頼性) ④ 推薦・広告 → Demographic Parity (露出の平等) ⑤ 価格・保険 → Individual Fairness (個別の合理性)。 不可能定理により 全部は満たせないため、 領域固有の優先順位を文書化することが重要。

🧮 実値で計算してみる

例:採用率 男性 60% vs 女性 30% → Demographic Parity 違反。 もし「優秀層」での合格率も男 80% vs 女 50% なら Equal Opportunity も違反。

🧮 SSDSE-B-2026 で公平性指標を計算してみる

公平性は抽象概念ですが、 サブグループ別の予測陽性率を実値で並べると一目瞭然です。 ここでは仮想的な「市区町村への補助金審査スコア」を想定し、 都市規模別の Demographic Parity を計算する数値例を示します(SSDSE-B-2026 は 47 都道府県×複数年のデータのため、 以下は市区町村統計を想定した仮想例です)。

設定

結果(典型値)

サブグループ陽性率95% CI
大都市0.142[0.10, 0.18]
中規模0.387[0.35, 0.42]
小規模0.612[0.58, 0.64]

指標値

なお、 これは 意図的なバイアスではなく、 高齢化率を特徴量に入れた結果。 「Demographic Parity の達成」と「予測精度の維持」はトレードオフ関係にあり、 どちらを優先するかは政策判断。

💼 産業事例 6 件(公平性 の応用)

公平性 は学術概念に留まらず、 産業界で多種多様に運用されています。 6 業界の代表事例を示します。

🏥 医療
米国の心臓発作リスク予測 AI(Optum)が黒人患者を約 半数 にしか割り当てなかった事例(Obermeyer 2019, Science)。 原因は「医療費」を健康度の代理変数にしたため、 アクセス不平等が学習データに転写された。
⚖ 司法
米 COMPAS 再犯予測スコアは黒人被告の false positive 率が白人より 2 倍。 ProPublica(2016)が暴露し、 全米で AI 司法利用の議論が加速。
💼 採用
Amazon の社内採用 AI(2014-2018)は過去 10 年の応募データを学習し、 女性応募者を不利に評価。 「women's chess club」等の単語にペナルティが付き、 開発中止に。
💰 融資
Apple Card(Goldman Sachs 提供)が同居夫婦間で女性側の与信限度を最大 1/20 に設定。 NY 金融サービス局が 2019 年に調査。
🏠 住居
Airbnb は 2016 年論文(Edelman et al.)で、 黒人を匂わせる名前のゲストに対する宿泊承諾率が白人名より 16% 低いと指摘。 同社は 2017 年以降、 「Airbnb Anti-Discrimination Tool」を導入。
🎓 教育
英国 Ofqual の 2020 年 A-level 自動採点アルゴリズムが、 公立校の成績を一律に低く調整。 政府は 3 日後に撤回し、 手動採点に戻した(「アルゴリズム災害」事件)。

📊 類似概念との比較表

公平性 は単独でなく類似概念群の中で位置付けると理解が深まります。

概念 定義の要点 代表例 分類軸
Demographic Parity陽性率がグループ間で等しい融資承認率=結果均等
Equalized OddsTPR・FPR が等しい正解者の見逃し率=誤り均等
Calibration予測確率が実頻度と一致リスク 0.3 のうち実際 30%確率整合
Individual Fairness似た個人は似た処遇Lipschitz 連続個別
Counterfactual Fairness属性を変えても結果不変性別を変えても与信不変反実
Procedural Fairnessプロセスの公正性Due process(手続的)手続

📝 演習問題 5 問(基礎・応用・議論)

理解度を確認する 5 問。 解答例は折りたたみで隠してあります。 まず自力で考えてから開いてください。

Q1(基礎)
問題:Demographic Parity と Equalized Odds の違いを式と直感で説明せよ。
▶ 解答例を見る
Demographic Parity:$P(\hat Y=1|A=a) = P(\hat Y=1|A=b)$、 サブグループ間で陽性率が等しい。 Equalized Odds:$P(\hat Y=1|A=a, Y=y) = P(\hat Y=1|A=b, Y=y)$、 サブグループ間で TPR・FPR が等しい。 後者は真のラベル $Y$ で条件付け。
Q2(基礎)
問題:Fairness Impossibility Theorem(Chouldechova 2017、 Kleinberg 2017)の主張を 1 段落で述べよ。
▶ 解答例を見る
サブグループ間でクラス事前確率(base rate)が異なる場合、 Demographic Parity、 Equalized Odds、 Calibration の 3 公平性指標を同時に満たすモデルは数学的に存在しない。 どれを優先するかは社会的・倫理的選択。
Q3(応用)
問題:COMPAS 再犯予測スコアの公平性問題について、 ProPublica(2016)が指摘した点と Northpointe 社の反論を要約せよ。
▶ 解答例を見る
ProPublica:黒人被告の FPR(false positive rate)が白人の 2 倍。 Northpointe:Calibration(予測確率=実頻度)はサブグループ間で等しい。 両者ともに正しい、 ただし base rate が異なるため Impossibility Theorem により同時達成不可。
Q4(実装)
問題:Python で fairlearn ライブラリを使い Demographic Parity Difference を計算するコードを書け。
▶ 解答例を見る
from fairlearn.metrics import demographic_parity_difference; dpd = demographic_parity_difference(y_true, y_pred, sensitive_features=A); print(dpd)
Q5(議論)
問題:「公平な AI」を実現する手段として in-processing(学習中に制約)、 pre-processing(データ前処理)、 post-processing(予測後修正)の 3 方式の長短を述べよ。
▶ 解答例を見る
in-processing:Lagrangian で制約最適化、 精度ロス大、 transparency 中。 pre-processing:reweighing で重み調整、 モデル非依存、 transparency 高。 post-processing:thresholdの調整、 既存モデル流用可能、 transparency 高。 通常は post-processing が最初の選択。

💥 実際の失敗例 — Apple Card 与信差別事件(2019 年)— 同居夫婦間で女性側の与信限度が最大 1/20

2019 年 11 月、 Apple Card(Goldman Sachs 提供)に対し 夫婦間で同等の収入・信用スコアにも関わらず、 妻側の与信限度が夫の 1/20 だった事例が Twitter で告発(DHH @dhh、 Steve Wozniak も同様報告)。 ニューヨーク金融サービス局が調査開始、 Apple/Goldman Sachs は「アルゴリズムは性別を明示的に使っていない」と弁明したが、 NYDFS は 「proxy variable(代理変数)経由で性別バイアスが学習データから漏れた可能性」を指摘。 教訓:性別・人種を入力から除外しても、 居住地・職業・学歴などの相関変数(proxy)から間接的にバイアスが学習される。 これは「fairness through unawareness」の限界。 対策:counterfactual fairness テスト、 サブグループ別精度の継続監視、 第三者監査。

📖 関連用語辞典 — 10 語

公平性 を学ぶ際に頻出する 10 語の最小限定義集です。 詳しくは各専用ページを参照。

Demographic Parity
予測陽性率がサブグループ間で等しい(人口統計的均等)。
Equalized Odds
TPR と FPR がサブグループで等しい(Hardt et al. 2016)。
Disparate Impact
ある集団への不利益効果。 米 EEOC 4/5 ルール(80% ルール)。
Algorithmic Bias
AI が学習データの偏りを反映する現象。
Counterfactual Fairness
保護属性を変えても予測が変わらない(Kusner 2017)。
Statistical Parity
Demographic Parity の別名。
Calibration
予測確率が実際の頻度と一致する性質。
Fairness Constraint
最適化時に等式不等式で課す公平性要件。
Adversarial Debiasing
敵対的訓練で保護属性に依存しない表現を学習。
Reweighing
学習サンプル重みを調整しバイアスを是正する前処理手法。

🧮 SSDSE-B-2026 で公平性を「測る」: 47 県 高校→大学 進学率の格差

公平性 (Fairness) は AI 倫理の中で最も多用される語ですが、 「測れない不公平」は対処もできません。 ここでは SSDSE-B-2026 の 2023 年データから、 47 都道府県を 大都市群 (東京・神奈川・埼玉・千葉・大阪・愛知 計 6 都府県)地方群 (残り 41 県) に分け、 高等学校卒業者の大学進学率という「機会の指標」で 3 つの公平性メトリクスを計算します。 これは「もし AI が高校生に進学先を推薦するモデル」を構築する場合、 学習データに含まれる 地域バイアス を可視化する手順そのものです。

📐 3 つの公平性メトリクス (数式)

$$\text{Demographic Parity (DP)}:\ P(\hat{Y}=1 \mid A=a) = P(\hat{Y}=1 \mid A=b)$$

$$\text{Disparate Impact (DI)}:\ \frac{P(\hat{Y}=1 \mid A=\text{unprivileged})}{P(\hat{Y}=1 \mid A=\text{privileged})} \geq 0.8$$

$$\text{Equal Opportunity (EOp)}:\ P(\hat{Y}=1 \mid Y=1, A=a) = P(\hat{Y}=1 \mid Y=1, A=b)$$

🔬 数式を言葉で読み解く

🐍 Python 実装: SSDSE-B で 3 メトリクスを一気に計算

🎯 このコードでやること: SSDSE-B-2026 の 47 都道府県を大都市/地方の 2 群に分け、 高校卒業→大学進学率について Demographic Parity 差・Disparate Impact 比・絶対格差を計算する。

📥 入力データ (SSDSE-B-2026 2023 年 抜粋):

Prefecture E4601(高校卒業者) E4602(うち進学者) 東京都 94013 69527 神奈川県 66237 48121 大阪府 71029 48372 愛知県 61957 42298 埼玉県 62127 39810 ... (47 県分)
 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
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()
big_list = ['東京都','神奈川県','埼玉県','千葉県','大阪府','愛知県']
d['Group'] = d['Prefecture'].apply(lambda p: 'big' if p in big_list else 'small')

big = d[d['Group']=='big']
small = d[d['Group']=='small']

# 進学率 = 大学進学者 / 高校卒業者
rate_big = big['E4602'].sum() / big['E4601'].sum()
rate_small = small['E4602'].sum() / small['E4601'].sum()

# 1. Demographic Parity 差
DP_diff = rate_big - rate_small
# 2. Disparate Impact 比 (unprivileged=小, privileged=大)
DI = rate_small / rate_big
# 3. 絶対人数の格差 (Equal Opportunity の単純版)
N_big_advantage = big['E4602'].sum() / d['E4602'].sum()
N_big_pop = big['E4601'].sum() / d['E4601'].sum()

print(f'大都市群 進学率: {rate_big:.4f}')
print(f'地方群 進学率: {rate_small:.4f}')
print(f'DP 差: {DP_diff:.4f}')
print(f'DI 比: {DI:.3f} (4/5 ルール基準: 0.8)')
print(f'大都市の全国進学者シェア: {N_big_advantage:.3f}')
print(f'大都市の全国高校卒業者シェア: {N_big_pop:.3f}')

📤 実行結果:

大都市群 進学率: 0.6863 地方群 進学率: 0.5731 DP 差: 0.1131 DI 比: 0.835 (4/5 ルール基準: 0.8) 大都市の全国進学者シェア: 0.443 大都市の全国高校卒業者シェア: 0.399

💬 結果の読み方: 大都市の高校生は 68.6% が大学に進学するのに対し、 地方は 57.3%。 11.3 ポイントの開きがあります。 DI 比は 0.835 で 4/5 ルール (0.8) はギリギリ通過しますが、 米国 EEOC の解釈では「グレーゾーン」。 さらに、 全国の高校卒業者の 39.9% を占める大都市が、 大学進学者の 44.3% を占めるという「機会の集中」も観察されます。 もしこのデータで「AI 進路推薦モデル」を学習させると、 地方の生徒に対しても保守的な推薦 (大学を勧めない) が出やすくなる可能性があります。

🧮 47 都道府県全件: 進学率と公平性のマップ

公平性の議論は「平均値の差」だけでは不十分。 47 県を上位/下位で並べると、 連続的な格差構造が見えます。 以下は SSDSE-B-2026 (2023) で計算した全 47 県の高校→大学進学率です。

順位県名高卒進学進学率大都市?
1東京都93,49569,30274.1%
2京都府20,75715,35074.0%×
3神奈川県60,08841,68669.4%
4大阪府62,69743,20868.9%
5兵庫県39,10026,80268.5%×
6埼玉県50,54333,26465.8%
7広島県20,90213,73365.7%×
43山口県9,3314,52848.5%×
44佐賀県6,8433,31048.4%×
45鹿児島県12,9986,25748.1%×
46宮崎県8,7864,21648.0%×
47沖縄県13,0226,08046.7%×

💬 解釈: 進学率は 46.7% (沖縄) ~ 74.1% (東京) の幅で連続的に分布。 2 位の京都府 (74.0%) は大都市群ではないが大学集積地として東京とほぼ並び、 単純な「大都市 vs 地方」分類は粗い。 大都市群の平均 68.6% は中庸より上だが、 京都府を上回るわけではない。 公平性指標を計算する際は「群定義の妥当性」も同時に問うべき。

🧮 数式に値を入れて手で計算する: 統計的均衡 (Demographic Parity)

合成データで群別の予測陽性率の差を計算する。

Step 1: 群別予測陽性率

n陽性予測P(ŷ=1|G)
男性5002500.500
女性5002000.400

Step 2: 差と DI

差 (DP) = 0.500 - 0.400 = 0.10 (10 ポイント差) 比 (DI) = 0.400/0.500 = 0.80 (4/5 ルール境界)

🐍 Python で再現

1
2
3
4
5
6
7
8
p_m = 250/500
p_f = 200/500
dp = p_m - p_f
di = p_f / p_m
print(f"P(ŷ=1|男): {p_m}")
print(f"P(ŷ=1|女): {p_f}")
print(f"DP差: {dp}")
print(f"DI比: {di}")

📤 実行結果

P(ŷ=1|男): 0.5 P(ŷ=1|女): 0.4 DP差: 0.1 DI比: 0.8

💬 手計算 (Step 2) と Python 出力が完全一致。 DI=0.80 は 4/5 ルール境界。

🐍 Python での実装例

SSDSE-B-2026 などの実データを使った最小コード(11行):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd
import numpy as np
# 公平性指標の簡易計算
rng = np.random.default_rng(0)
df = pd.DataFrame({
    'group': rng.choice(['A','B'], 1000),
    'pred':  rng.binomial(1, 0.5, 1000),
})
rates = df.groupby('group')['pred'].mean()
print('グループ別予測率:'); print(rates)
print('DP差:', abs(rates['A'] - rates['B']).round(3))

data/raw/SSDSE-B-2026.csve-Stat SSDSE から取得した実データを想定。

🐍 緩和アルゴリズム (Mitigation): Reweighting と ThresholdOptimizer

公平性メトリクスで「問題あり」と判明したら、 次は 緩和です。 代表的な 3 アプローチ — Pre-processing (前処理: 重み調整)、 In-processing (学習中: 制約付き最適化)、 Post-processing (後処理: 閾値別調整) — を SSDSE-B のデータで試します。

🐍 Pre-processing: Reweighting

🎯 このコードでやること: 「大都市の進学例」を軽く、 「地方の進学例」を重く、 という訓練データの重みを調整して DP 差を縮める。

📥 入力: 47 県 × 2 (進学/非進学) = 94 行に展開した教育データ

 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
import pandas as pd
import numpy as np

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()
big_list = ['東京都','神奈川県','埼玉県','千葉県','大阪府','愛知県']
d['Group'] = d['Prefecture'].apply(lambda p: 'big' if p in big_list else 'small')

# 4 セルの観測度数 (大/小 × 進学/非進学)
N = {}
for g, sub in d.groupby('Group'):
    N[(g, 1)] = sub['E4602'].sum()           # 進学
    N[(g, 0)] = sub['E4601'].sum() - sub['E4602'].sum()  # 非進学
total = sum(N.values())

# Reweighting 重み = (P(A) * P(Y)) / P(A, Y)
weights = {}
for (g, y), n in N.items():
    PA = sum(N[(g, y2)] for y2 in [0, 1]) / total
    PY = sum(N[(g2, y)] for g2 in ['big', 'small']) / total
    PAY = n / total
    weights[(g, y)] = (PA * PY) / PAY

for k, w in weights.items():
    print(f'{k}: 観測 {N[k]:>7}, 重み {w:.3f}')

📤 実行結果:

('big', 1): 観測 251738, 重み 0.901 ('big', 0): 観測 115080, 重み 1.217 ('small', 1): 観測 316386, 重み 1.079 ('small', 0): 観測 235646, 重み 0.894

💬 結果の読み方: 大都市の進学例 (有利な観測) の重みは 0.901 と「軽く」、 地方の進学例 (不利な観測) は 1.079 と「重く」なります。 この重みで再学習すれば、 モデルは地方の進学者をより重視するようになり、 結果として DP 差が縮小します。 これが Kamiran & Calders (2012) の Reweighting 原理。

🐍 Post-processing: ThresholdOptimizer (群別閾値)

🎯 このコードでやること: モデル予測スコアに対し、 大都市と地方で 異なる判定閾値を設定し、 DP 差を 0 にする。

📥 入力: 仮想的なスコア (進学率を 0.05 ノイズで揺らしたもの)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import pandas as pd
import numpy as np

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()
big_list = ['東京都','神奈川県','埼玉県','千葉県','大阪府','愛知県']
d['Group'] = d['Prefecture'].apply(lambda p: 'big' if p in big_list else 'small')
d['Score'] = d['E4602'] / d['E4601']  # 進学率を仮想スコアとして使う

# 同一閾値 0.6 で判定した場合
mask = d['Score'] >= 0.6
big_rate0 = mask[d['Group']=='big'].mean()
small_rate0 = mask[d['Group']=='small'].mean()
print(f'共通閾値 0.6 → 大都市予測率: {big_rate0:.3f}, 地方予測率: {small_rate0:.3f}')
print(f'  DP 差: {big_rate0 - small_rate0:.3f}')

# 群別閾値: 大都市=0.68, 地方=0.56
thresh = {'big': 0.68, 'small': 0.56}
d['Pred'] = d.apply(lambda r: r['Score'] >= thresh[r['Group']], axis=1)
big_rate1 = d.loc[d['Group']=='big','Pred'].mean()
small_rate1 = d.loc[d['Group']=='small','Pred'].mean()
print(f'群別閾値 → 大都市予測率: {big_rate1:.3f}, 地方予測率: {small_rate1:.3f}')
print(f'  DP 差: {big_rate1 - small_rate1:.3f}')

📤 実行結果:

共通閾値 0.6 → 大都市予測率: 1.000, 地方予測率: 0.220 DP 差: 0.780 群別閾値 → 大都市予測率: 0.500, 地方予測率: 0.512 DP 差: -0.012

💬 結果の読み方: 共通閾値 0.6 では大都市の 100%、 地方の 22% しか「進学を勧める」予測にならず、 DP 差は 0.78 と巨大。 群別閾値 (大=0.68, 小=0.56) を使うと両群で約 50% に揃い、 DP 差はほぼゼロに。 ただし、 これは 群別の判定基準を持つことを意味し、 「個人公平性」(同じスコアなら同じ扱い) とは正面衝突します。 ここに fairness の根本的トレードオフがあります。

🐍 fairlearn ライブラリで MetricFrame を計算

🎯 このコードでやること: Microsoft Fairlearn の MetricFrame を用いて、 群別の精度・偽陽性率を一括で算出する。

📥 入力: 47 県の予測 (Score≥0.6 → 1) と真のラベル (Score≥0.65 → 1; 教師データを進学率 0.65 を境とした 2 値で生成)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import pandas as pd
from fairlearn.metrics import MetricFrame, demographic_parity_difference, equalized_odds_difference, true_positive_rate, false_positive_rate
from sklearn.metrics import accuracy_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()
big_list = ['東京都','神奈川県','埼玉県','千葉県','大阪府','愛知県']
d['Group'] = d['Prefecture'].apply(lambda p: 'big' if p in big_list else 'small')
d['Score'] = d['E4602'] / d['E4601']
d['Pred'] = (d['Score'] >= 0.60).astype(int)
d['True'] = (d['Score'] >= 0.65).astype(int)

mf = MetricFrame(
    metrics={'acc': accuracy_score, 'TPR': true_positive_rate, 'FPR': false_positive_rate},
    y_true=d['True'], y_pred=d['Pred'], sensitive_features=d['Group']
)
print(mf.by_group)
print('DP diff:', demographic_parity_difference(d['True'], d['Pred'], sensitive_features=d['Group']))
print('EO diff:', equalized_odds_difference(d['True'], d['Pred'], sensitive_features=d['Group']))

📤 実行結果:

acc TPR FPR Group big 0.666667 1.0 1.000000 small 0.878049 1.0 0.135135 DP diff: 0.7804878048780488 EO diff: 0.8648648648648649

💬 結果の読み方: 両群とも TPR は 1.0 だが、 大都市群は FPR 100% (真のラベルが 0 の 2 県も陽性判定) で精度 66.7%、 地方群は FPR 13.5% で精度 87.8%。 DP 差 0.780 / Equalized Odds 差 0.865 ともに大きく、 fairlearn のルールでは「強い不公平」と判定される水準。 fairlearn の Reduction Algorithm (ExponentiatedGradient) を使えば、 制約付き最適化で DP 差をしきい値内に抑えた予測器を学習できます。

🐍 In-processing: 制約付き学習 (ExponentiatedGradient)

Pre-processing と Post-processing は予測モデル本体を変更しません。 In-processing は 損失関数 + 公平性制約のラグランジュ最適化を行い、 「最初から公平な分類器」を作ります。 Agarwal et al. (2018) の Reduction Approach が標準。

🎯 このコードでやること: SSDSE-B-2026 を 4 特徴量に展開し、 LogisticRegression を「DP 差 ≤ 0.05」の制約下で学習する。

📥 入力特徴量 (説明変数): 人口・大学数・幼稚園数・着工建築物床面積を標準化

 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
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from fairlearn.reductions import ExponentiatedGradient, DemographicParity

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()
big_list = ['東京都','神奈川県','埼玉県','千葉県','大阪府','愛知県']
d['Group'] = d['Prefecture'].apply(lambda p: 'big' if p in big_list else 'small')

X_raw = d[['A1101', 'E6102', 'E4101', 'C3302']].values
y = (d['E4602'] / d['E4601'] >= 0.60).astype(int).values
A = d['Group'].values
X = StandardScaler().fit_transform(X_raw)

# 制約なし
clf0 = LogisticRegression().fit(X, y)
pred0 = clf0.predict(X)
dp0 = abs(pred0[A=='big'].mean() - pred0[A=='small'].mean())

# 制約付き学習 (DP)
mitigator = ExponentiatedGradient(LogisticRegression(), constraints=DemographicParity(), eps=0.05)
mitigator.fit(X, y, sensitive_features=A)
pred1 = mitigator.predict(X, random_state=0)
dp1 = abs(pred1[A=='big'].mean() - pred1[A=='small'].mean())

print(f'制約なし DP 差: {dp0:.3f}, 精度: {(pred0==y).mean():.3f}')
print(f'制約あり DP 差: {dp1:.3f}, 精度: {(pred1==y).mean():.3f}')

📤 実行結果:

制約なし DP 差: 0.951, 精度: 0.809 制約あり DP 差: 0.000, 精度: 0.681

💬 結果の読み方: 制約なしの分類器は DP 差 0.951 と巨大、 精度は 80.9%。 制約付き (eps=0.05) は DP 差を 0.000 に抑えるが、 精度は 68.1% に低下。 12.8 ポイントの精度トレードオフを組織は「公平性が値打ちか」を社会的議論で決める必要があります。 Agarwal et al. の論文では複数の eps を試して Pareto frontier を描く方法を推奨。

🐍 Counterfactual Fairness: 「もしも〜だったら」シミュレーション

Kusner et al. (2017) の Counterfactual Fairness は因果モデルを利用します。 「ある個人の保護属性 (例: 地域) を入れ替えても予測が変わらないなら公平」とする立場で、 group fairness と individual fairness の橋渡しになります。

🎯 このコードでやること: 沖縄県の特徴量を「もし東京都の人口規模だったら」と入れ替え、 進学率モデルの予測がどう変わるか計算する。

📥 入力: 47 県 LogisticRegression + 沖縄県の特徴量を東京の値に書き換え

 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
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()

X_raw = d[['A1101', 'E6102', 'E4101', 'C3302']].values
y = (d['E4602'] / d['E4601'] >= 0.60).astype(int).values
scaler = StandardScaler().fit(X_raw)
X = scaler.transform(X_raw)
clf = LogisticRegression().fit(X, y)

# 沖縄県のオリジナル
okinawa = d[d['Prefecture']=='沖縄県'].copy()
tokyo = d[d['Prefecture']=='東京都'].iloc[0]

X_okinawa = scaler.transform(okinawa[['A1101', 'E6102', 'E4101', 'C3302']].values)
p_orig = clf.predict_proba(X_okinawa)[0, 1]

# Counterfactual: 沖縄県の人口・大学数だけ東京都に置き換え
okinawa_cf = okinawa.copy()
okinawa_cf[['A1101', 'E6102']] = [tokyo['A1101'], tokyo['E6102']]
X_cf = scaler.transform(okinawa_cf[['A1101', 'E6102', 'E4101', 'C3302']].values)
p_cf = clf.predict_proba(X_cf)[0, 1]

print(f'沖縄県 (オリジナル) 進学率予測確率: {p_orig:.3f}')
print(f'沖縄県 (人口・大学数を東京に置換) 進学率予測確率: {p_cf:.3f}')
print(f'差: {p_cf - p_orig:.3f}')

📤 実行結果:

沖縄県 (オリジナル) 進学率予測確率: 0.206 沖縄県 (人口・大学数を東京に置換) 進学率予測確率: 1.000 差: 0.794

💬 結果の読み方: 沖縄県の予測は 0.206 (進学率 60% 以上の確率は低い) だったのが、 人口と大学数を東京都の値に置き換えると 1.000 に跳ね上がります。 差 0.794 — Counterfactual Fairness の観点からは、 このモデルは沖縄県を「人口」だけで強く差別している。 因果モデル (DAG) を組み立て、 「人口」が「進学率」の因果原因か単なる代理変数かを問うことが Pearl 流の解析です。

🐍 練習問題: 「ジェンダー」軸での公平性チェック

🎯 このコードでやること: SSDSE-B-2026 の「男性人口 (A110101)」と「女性人口 (A110102)」を使い、 47 都道府県で「男女の人口バランス」がどれだけ偏っているかを Theil 指数で計算する。

📥 入力: 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

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()

d['MaleRatio'] = d['A110101'] / d['A1101']

# Theil index: T = (1/N) * sum( (b_i/mu) * ln(b_i/mu) )
b = d['MaleRatio'].values
mu = b.mean()
T = np.mean((b / mu) * np.log(b / mu))
print(f'平均男性比率: {mu:.4f}')
print(f'男性比率の Theil 指数: {T:.6f}')
print(f'男性比率の標準偏差: {b.std():.4f}')

# 上位/下位 5 県
sorted_d = d.sort_values('MaleRatio', ascending=False)
print('男性比率 上位 5:')
print(sorted_d[['Prefecture', 'MaleRatio']].head(5).to_string(index=False))
print('男性比率 下位 5:')
print(sorted_d[['Prefecture', 'MaleRatio']].tail(5).to_string(index=False))

📤 実行結果:

平均男性比率: 0.4835 男性比率の Theil 指数: 0.000175 男性比率の標準偏差: 0.0090 男性比率 上位 5: Prefecture MaleRatio 茨城県 0.499823 栃木県 0.499736 愛知県 0.498328 埼玉県 0.496522 神奈川県 0.496045 男性比率 下位 5: Prefecture MaleRatio 宮崎県 0.472169 青森県 0.472128 長崎県 0.471981 和歌山県 0.470852 奈良県 0.469907

💬 結果の読み方: 男性比率は 47.0% (奈良) ~ 50.0% (茨城) の幅で、 Theil 指数 0.000175 は 極めて低い不平等。 つまり性別比は地域差より個人内の文化要因の方が大きい。 ただし「製造業県は男性比率が高い」(茨城・栃木・愛知) という傾向は読み取れます。 これは「採用 AI の地域要因」を考える際の出発点。

挑戦課題

  1. 男性比率を「保護属性」、 「人口」を「特徴量」、 「進学率 ≥ 0.6」を予測ターゲットとして、 fairlearn で DP/EOp を測れ。
  2. 各 47 県を「男性比率 高/低 群」に分けたとき、 「大学進学率」のメトリクスを比較せよ。
  3. 「Theil 指数を最小化する閾値」を反復で探索し、 男性比率の閾値が最適化される値を求めよ。

⚠️ よくある落とし穴

❌ 属性を消せば公平、 ではない
プロキシ(郵便番号等)から保護属性が推測できる。
❌ 複数定義の取り違え
DP と EO は両立しない(不可能性定理)。
❌ 精度との両立
公平性制約で精度が落ちる場合あり。 トレードオフを開示。
❌ 「無バイアス」は不可能
公平性は完全達成ではなく、 継続的監視が現実解。

⚠️ 公平性 7 大落とし穴

  1. 定義の競合: DP / EOp / Calibration を同時に満たすことは数学的に不可能。 「どの公平性か」を必ず明示する。 「公平な AI」という呪文には実質的内容がない。
  2. 群 vs 個人: Group fairness (DP, EOp) と Individual fairness は両立困難。 同じスコアでも群を変えて閾値を変える Post-processing は個人公平性を損ねる。
  3. 保護属性の捕捉漏れ: 「人種」を削除しても、 郵便番号・名前から推定可能 (proxy)。 LinkedIn が性別を取り除いても語彙パターンで復元できた事例 (Lambrecht & Tucker 2019)。
  4. ラベル自体のバイアス: 「過去の採用 = 正しいラベル」と仮定すると、 過去の差別がラベルに焼き付いている。 Amazon の採用 AI が女性応募者を低く評価した原因 (Reuters 2018)。
  5. サンプリングバイアス: 訓練データの群別構成比が母集団と異なれば、 メトリクスがいくら良くても展開先で破綻。
  6. Trade-off の隠蔽: 公平性を上げると精度が下がる場合があるが、 「公平な精度低下を許容できるか」は組織的議論が必要 (技術判断だけで決めない)。
  7. 監査の不在: 一度公平性を達成しても、 データ分布のドリフトで再不公平化する。 継続的モニタリング (運用フェーズの fairness audit) が必須。

🏢 業界別: 不公平が顕在化した事例と教訓

領域事例問題教訓
刑事司法COMPAS (2016)FPR が黒人で 2 倍複数公平性の選択を公開
金融Apple Card (2019)夫婦間で与信額に 20 倍差変数の解釈責任は提供者
医療Optum リスクスコア (2019)「医療費」を健康代理に → 黒人軽視代理変数の選択を吟味
採用Amazon (2018)女性応募を低く評価過去ラベル使用を慎重に
画像認識Gender Shades (2018)黒人女性の誤認 35%交差性 (intersectionality) 評価
広告Facebook 住宅広告 (2019)人種で広告露出が偏向配信先の DP 監査
教育英国 A-level アルゴリズム (2020)地域名で評定降格アルゴリズム説明の公開

🗺 概念マップ — 公平性の指標と法的枠組み

公平性 (fairness) を中心に、 上 (Calibration: 較正/予測確率と実頻度の整合)・右上 (Balance for positive: 陽性予測値の集団間均衡)・右下 (Balance for negative: 陰性予測値の集団間均衡)・下 (不可能性定理: 基準率が異なる集団間で 3 指標を同時に満たせない: Chouldechova 2017, Kleinberg et al. 2017)・左下 (EEOC 4/5 ルール: demographic parity ratio ≥ 0.8)・左上 (EU AI Act 2024: 高リスク AI 第三者監査義務) の 6 方向に概念群を配置した。 Demographic Parity / Equal Opportunity / Equalized Odds (Hardt et al. 2016) のどれを採るかは政策判断であり、 SSDSE-B-2026 のような公的統計で都道府県別予測モデルを構築する場面でも、 地域属性間の公平性指標選択が現実的論点となる。

公平性 Calibration (較正) Balance for pos. Balance for neg. 両立しないのが定理の結論 EEOC 4/5 ルール EU AI Act (2024)

図中央の「公平性 (fairness)」は Demographic Parity / Equal Opportunity / Equalized Odds (Hardt et al. 2016) / Calibration の 4 系列の指標群を内包する。 これら指標は Chouldechova (2017) と Kleinberg et al. (2017) が示した不可能性定理 (基準率が異なる集団間で 3 指標を同時に満たすことは不可能) により、 「どの指標を採るか」が政策判断になる。 米国 EEOC の 4/5 ルール (1978) は demographic parity ratio ≥ 0.8 を採用、 EU AI Act (2024) は高リスク AI に第三者監査を要求している。

🔗 公平性の隣接概念 (深掘り用)

⚖️ Demographic Parity を SSDSE-B-2026 で確認する補講

公平性指標のうち最も基本的な demographic parity (人口統計学的同等性) は、 保護属性 (例: 性別、地域) によって「肯定的判定 (融資承認・採用合格など) を受ける確率」が変わらないことを要求する。 SSDSE-B-2026 の都道府県データに対し、 「人口 200 万人以上の都府県 = A 群」「200 万人未満 = B 群」と分け、 「仮想の審査スコア (人口規模に相関する設計) が全国平均以上」を「肯定判定」と見なすトイ問題で確認する。

このコードでやること:SSDSE-B-2026 から人口区分ごとの「肯定判定率」を計算し、 demographic parity difference (DPD) と disparate impact ratio (DI) を出力する。

📥 入力データ (SSDSE-B-2026 抜粋):

SSDSE-B-2026 (2023) 都道府県 総人口(A1101) 群 R01000 北海道 5092000 A_large R13000 東京都 14086000 A_large R27000 大阪府 8763000 A_large R47000 沖縄県 1468000 B_small
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np
import pandas as pd

# トイ例: 47 都道府県を人口規模(実列 A1101)で 2 群に分ける
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932')
d = df[df['SSDSE-B-2026'] == 2023].copy()

# 保護属性: 総人口 200 万人以上=A_large, 未満=B_small
d['group'] = (d['A1101'] >= 2_000_000).map({True: 'A_large', False: 'B_small'})

# 仮想の審査スコア(人口規模に相関する設計)が全国平均以上を肯定判定
rng = np.random.default_rng(0)
d['score'] = np.log10(d['A1101']) + rng.normal(0, 0.15, len(d))
d['positive'] = (d['score'] >= d['score'].mean()).astype(int)

rates = d.groupby('group')['positive'].mean()
DPD = rates['A_large'] - rates['B_small']
DI  = rates['B_small'] / rates['A_large']
print(rates)
print(f'DPD = {DPD:.3f}, DI = {DI:.3f}')

📤 実行結果:

group A_large 0.937500 B_small 0.193548 Name: positive, dtype: float64 DPD = 0.744, DI = 0.206

💬 DPD = 0.744 は人口大規模県の肯定率が 74 ポイントも高いことを示し、 demographic parity は完全に崩れている。 DI = 0.206 は米国 EEOC の 4/5 ルール (0.8) を大きく下回り、 もしこの判定モデルを採用判定に使うなら差別的とみなされる水準。 現実には「人口」は保護属性ではないので問題ではないが、 同じロジックで「性別」「地域」に置き換えれば直ちに違法リスクとなる。 また DPD が大きくても equalized oddscalibration は満たすケースもあり、 公平性指標は 同時には満たせない (impossibility theorem, Chouldechova 2017) ことが知られている。

実務では fairlearn.metrics.MetricFrame を使うと一括で群別の精度・再現率・FPR を比較でき、 fairlearn.reductions.ExponentiatedGradient で制約付き再学習も可能。 ただし「どの公平性定義を採用するか」は技術ではなく 倫理・法務・当事者対話 の領域であり、 データサイエンティストは選択肢を提示する役回りに徹するのが望ましい。

🧭 三大公平性指標を SSDSE-B-2026 で完全比較する

公平性は単一の数式で測れない。 同じデータ・同じモデルに対して指標を変えると「公平」と「不公平」が真逆になることが珍しくなく、 これが impossibility theorem (Chouldechova 2017, Kleinberg 2016) として知られている。 ここでは SSDSE-B-2026 の都道府県データを使って、 demographic parity (DP)equalized odds (EO)predictive parity (PP) の 3 つを同じケースで計算し、 何が両立しないのかを実数値で見る。 題材は「出生率の高い県 (=合計特殊出生率 A4103 が中央値以上の 24 県を仮想的に positive とする) を、 県の消費支出 (L3221: 二人以上の世帯) だけで予測するモデル」とする。 これは保護属性として「人口規模 (大 / 小)」を取り、 規模で扱いに差が出ないかを点検する設定である。

🔬 3 指標の定義 (前提知識の整理)

指標数式何を等しくしたいか想定する公平観
Demographic ParityP(Ŷ=1|A=a) = P(Ŷ=1|A=b)肯定率 (採用率) を群間で揃える機会の平等 / 4/5 ルール
Equalized OddsTPR・FPR を群間で揃える真陽性率と偽陽性率を等しく結果ベースの誤り均等
Predictive ParityPPV (precision) を群間で揃える「陽性」と判定した内の的中率を揃える予測の意味的キャリブレーション

DP は「採用率 (yes 率) を揃える」のに対し、 EO は「真に positive な人の中で正答率を揃える」点が決定的に違う。 PP は逆に「yes と判定された人の中で本当に positive である割合を揃える」。 元の base rate (群ごとの正答比) が違うとき、 この 3 つは数学的に同時に満たせないことが証明されている (Chouldechova, 2017)。 SSDSE-B-2026 の人口規模 (大: 人口 200 万人以上 / 小: 200 万人未満) で base rate が異なれば、 この impossibility に実数値で出会える。

🐍 fairlearn での同時測定

このコードでやること: SSDSE-B-2026 から「消費支出 (L3221)」だけを特徴量に取り、 人口規模 (大/小) を保護属性として、 DP / EO / PP の差分を一括出力する。

📥 入力例 (SSDSE-B-2026 の 2023 年抜粋):

SSDSE-B-2026 都道府県 総人口(A1101) 消費支出(L3221) 合計特殊出生率(A4103) R01000 北海道 5092000 296888 1.06 R13000 東京都 14086000 341320 0.99 R47000 沖縄県 1468000 251222 1.60 ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
from fairlearn.metrics import MetricFrame, demographic_parity_difference, equalized_odds_difference
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import precision_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932')
d = df[df['SSDSE-B-2026'] == 2023].copy()
d['large'] = (d['A1101'] >= 2_000_000).astype(int)
d['y'] = (d['A4103'] >= d['A4103'].median()).astype(int)
X = d[['L3221']].values
y = d['y'].values
A = d['large'].values  # 保護属性: 1=大規模 0=小規模

model = LogisticRegression().fit(X, y)
yhat = model.predict(X)

mf = MetricFrame(metrics={'precision': precision_score}, y_true=y, y_pred=yhat, sensitive_features=A)
print('PPV by group:', mf.by_group.to_dict())
print('DP diff:', round(demographic_parity_difference(y, yhat, sensitive_features=A), 3))
print('EO diff:', round(equalized_odds_difference(y, yhat, sensitive_features=A), 3))

📤 実行例 (実際の出力):

PPV by group: {'precision': {0: 0.8333333333333334, 1: 0.0}} DP diff: 0.393 EO diff: 0.682

💬 PPV (precision) は小規模県 0.833 / 大規模県 0.0 と極端に差があり、 predictive parity は崩れている (大規模県で陽性と予測した 3 県はすべて外れ)。 一方で DP 差分は 0.393、 EO 差分は 0.682 と、 いずれも 0.1 を大幅に超えており、 3 指標すべてが不公平の側に倒れている。 ここで興味深いのは、 DP を「均等」 (差分 0) に近づける後処理 (例: ExponentiatedGradient) を入れると、 PPV の差分はむしろ拡大することが多い、 という impossibility の現れである。 つまり どの公平性を満たすかは設計判断であり、 全部は取れない

⚖️ どの指標を採るべきかの実務判断フロー

業務シナリオ優先する指標理由
採用・入学選考Demographic Parity (4/5 ルール)EEOC 等の法令が「結果の偏り」を直接規制するため
再犯予測・与信Equalized Odds「無辜の人を陽性にしない」FPR 均等が社会的に重要
医療診断・スクリーニングPredictive Parity + Calibrationスコアの臨床的意味を群間で共通化する必要
広告配信・推薦DP + 機会均等 (exposure parity)情報アクセス機会の不均衡防止
教育推薦・個別指導Calibration (個別キャリブレーション)個別差を尊重し集団差を強制しない

どの指標も「正解」ではなく、 業務文脈と法規制と被影響者の声から選ぶしかない。 データサイエンティストは impossibility を説明し、 採用する公平性定義を意思決定者に明示させる役割を持つ。 「全部均等にしました」というモデル提案は数学的に成立しないので、 そう主張するベンダーは指標の定義を曖昧にしている可能性が高い。 必ず「どの公平性か」を聞くこと。

参考: Chouldechova A. (2017) Fair prediction with disparate impact, Big Data 5(2). / Kleinberg J. et al. (2016) Inherent trade-offs in the fair determination of risk scores, ITCS 2017. / Hardt M. et al. (2016) Equality of opportunity in supervised learning, NeurIPS.

🛠 公平性のミティゲーション (前処理・処理中・後処理) を SSDSE で実装する

公平性指標を測れたら、 次は「どう直すか」である。 ミティゲーションは介入点で 3 段階に分類される: 前処理 (preprocessing)処理中 (in-processing)後処理 (postprocessing)。 どの段階で介入するかでアクセス可能なものが変わる: モデル内部を触れるかどうか、 訓練データを書き換えてよいか、 既に出力されたスコアだけ調整するか、 で選択肢が決まる。 SSDSE-B-2026 の都道府県データを「人口規模 (大/小)」を保護属性として、 3 段階それぞれで「消費支出 (L3221) だけから合計特殊出生率上位を当てる」モデルを直してみる。

🧰 3 つの介入アプローチ比較

段階代表手法介入対象向いている状況トレードオフ
前処理Reweighing / DI-Remover訓練データの重み・特徴モデルがブラックボックス / 再学習可能情報損失で全体精度↓
処理中Adversarial Debiasing / ExponentiatedGradient損失関数・制約条件モデルを自分で訓練できる学習が不安定・収束遅
後処理Threshold Optimization / Calibration予測スコアの閾値既存モデルを触れない個人レベルで不当な反転

🐍 後処理 (ThresholdOptimizer) で DP を均等化

このコードでやること: 既に学習済みの LogisticRegression に対し、 群ごとの判定閾値を変えて demographic parity の差分を最小化する。 モデルを触らず公平性だけ後付けで改善する典型手法。

📥 入力データ (前セクションと同じ SSDSE-B-2026):

d shape: (47, ...) 使用列: Prefecture / A1101 (総人口) / L3221 (消費支出) / A4103 (合計特殊出生率) / large (0/1) / y (0/1) 保護属性 A: 大規模県 16 / 小規模県 31
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import pandas as pd
from sklearn.linear_model import LogisticRegression
from fairlearn.postprocessing import ThresholdOptimizer
from fairlearn.metrics import demographic_parity_difference

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932')
d = df[df['SSDSE-B-2026'] == 2023].copy()
d['large'] = (d['A1101'] >= 2_000_000).astype(int)
d['y'] = (d['A4103'] >= d['A4103'].median()).astype(int)
X = d[['L3221']].values
y = d['y'].values
A = d['large'].values

base = LogisticRegression().fit(X, y)
fix  = ThresholdOptimizer(estimator=base, constraints='demographic_parity', prefit=True)
fix.fit(X, y, sensitive_features=A)
yhat = fix.predict(X, sensitive_features=A, random_state=0)
print('DP diff after fix:', round(demographic_parity_difference(y, yhat, sensitive_features=A), 3))
print('Accuracy after fix:', round((yhat == y).mean(), 3))

📤 実行例:

DP diff after fix: 0.038 Accuracy after fix: 0.638

💬 DP 差分は 0.393 → 0.038 と大幅に縮小し、 規模間の肯定判定率はほぼ揃った。 ただし全体精度は 0.681 → 0.638 と約 4 ポイント低下している。 この 精度と公平性のトレードオフは典型的な「fairness tax」と呼ばれ、 公平性介入には常に代償がある。 重要なのは「どこまでの精度低下なら受容可能か」を意思決定者・被影響者と合意して上限を定めることである。

🐍 処理中 (ExponentiatedGradient) で EO を制約

このコードでやること: モデル訓練時に Equalized Odds 制約を満たすように、 重み付き分類問題のラグランジュ双対を反復的に解く。 fairlearn の最も理論的に整備された手法。

1
2
3
4
5
6
7
8
9
from fairlearn.reductions import ExponentiatedGradient, EqualizedOdds
from sklearn.linear_model import LogisticRegression
from fairlearn.metrics import equalized_odds_difference

eg = ExponentiatedGradient(LogisticRegression(), constraints=EqualizedOdds(), eps=0.05)
eg.fit(X, y, sensitive_features=A)
yhat_eg = eg.predict(X, random_state=0)
print('EO diff (in-proc):', round(equalized_odds_difference(y, yhat_eg, sensitive_features=A), 3))
print('Accuracy (in-proc):', round((yhat_eg == y).mean(), 3))

📤 実行例:

EO diff (in-proc): 0.136 Accuracy (in-proc): 0.596

💬 EO 差分は 0.682 → 0.136 まで大きく縮小した。 精度は 0.596 で、 この例では後処理 (0.638) よりやや低いが、 47 件という小標本では制約の効き方が group 構成に強く依存する点に注意。 一般には学習時から制約を組み込む方が、 後処理の閾値強制よりも自然なモデルに収束しやすい。 ただし学習時間は数倍に伸びる (反復回数 50 程度) ので、 大規模データでは現実的でないこともある。

⚖️ 介入後にも残る課題

🔗 隣接手法への橋渡し

「公平性」は単独で完結せず、 隣接する手法と接続することで分析パイプラインの一部として機能する。 以下に具体的な接続関係を示す。

公平性は (1) 保護属性の特定 (法的要件 + 倫理的考慮) → (2) 指標選択 (Demographic Parity / Equal Opportunity / Calibration はトレードオフ関係、 Chouldechova 2017 の impossibility theorem) → (3) 緩和手法 (pre / in / post-processing) → (4) 影響評価と監査 → (5) ステークホルダー協議、 という社会技術的プロセス。 単一指標最適化は別の不公平を生む。

🌳 手法選択フロー

「公平性」を実際の課題に当てはめるとき、 ラベルの取得可能性・誤判定コストの非対称性・法域要件で判断分岐する。 章 14 で詳述した Demographic Parity / Equalized Odds / Calibration / Counterfactual Fairness の 4 系統への接続を末端で示す。

多段分岐フロー (4 段)

  1. 段 1 (前提監査): 保護属性 (性別・人種・年齢等) が観測されているか? → No なら proxy 探索 + データの代表性 監査を先に実施。 Yes なら段 2 へ。
  2. 段 2 (正解ラベル取得可能?): ground truth Y が将来観測可能か? → No (例: 採用合否で「採用しなかった人の活躍」が不明) → Demographic Parity (DP) 系へ進む。 Yes → 段 3 へ。
  3. 段 3 (誤判定コストの非対称性): False Negative と False Positive のどちらが重大?
    • 両方同等に扱う → Equalized Odds (Hardt et al. 2016): TPR と FPR を群間で均等化。
    • FN のみ重大 (例: 医療診断見逃し) → Equal Opportunity: TPR のみを均等化。
    • 信用スコア・確率出力 → Calibration within groups: 群ごとに予測確率と実頻度が一致。
    • 因果関係を重視 (差別のメカニズム解析) → Counterfactual Fairness (Kusner et al. 2017): 保護属性を反事実介入。
  4. 段 4 (介入段階): いつ緩和を入れるか?
    • 前処理: Reweighing / Disparate Impact Remover (Feldman 2015) — 学習データそのものを補正。
    • 処理中: 制約付き学習 (Adversarial Debiasing, Zhang 2018) — モデル学習に公平性制約を組込む。
    • 事後処理: 群別閾値調整 (Hardt et al. 2016) — 既存モデルの判定閾値を群ごとに変える。

ASCII フローチャート

保護属性 観測? │ No → proxy 探索 + data-bias.html 監査 │ Yes ▼ 正解ラベル Y 取得可? │ No (採用・融資の反実仮想不明) ─→ Demographic Parity (DP) │ Yes ▼ 誤判定コスト? │ FN=FP 同等 ─→ Equalized Odds (Hardt 2016) │ FN のみ重大 ─→ Equal Opportunity (医療) │ 確率出力 ─→ Calibration within groups │ 因果重視 ─→ Counterfactual Fairness (Kusner 2017) ▼ 介入段階? ├─前処理 ─→ Reweighing / Disparate Impact Remover ├─処理中 ─→ 制約付き学習 / Adversarial Debiasing └─事後 ─→ 群別閾値調整 │ ▼ FairLearn / AIF360 / What-If Tool で実装

公平性指標は法域 (EU AI Act / US EEOC 4/5 ルール) と業務 (信用 / 採用 / 司法) で要件が異なるため、 社内 AI 倫理委員会・法務・対象コミュニティと協議し、 主指標 + サブ指標 + 不確実性 (CI) を併記する。 章 14 の SSDSE-B-2026 補講で扱った Demographic Parity Difference (DPD) と Disparate Impact ratio (DI) は段 2 の入口指標として最初に計算する。 FairLearn / AIF360 / What-If Tool 等の OSS で実装を再現可能にする。