公平性:全体の正解率では見えない偏り
AIは、ローンの審査、採用の書類選考、病気の見落とし防止など、人に関わる判断に使われることがあります。このとき、グループによって、間違いの起きやすさが大きく違う と、特定のグループだけが不利益を受けることになります。
実験:作ったデータで確かめる
実在の人のデータではなく、実験のために作ったデータで確かめます。2つの数値(特徴量)から、陽性か陰性かを当てる問題です。
- グループA: 1800人
- グループB: 200人(少数)。Aとは、特徴量と正解の関係が少し違う
半分を訓練データ、半分をテストデータにして、ロジスティック回帰を学習させました。モデルは、グループの情報を使っていません(特徴量は2つの数値だけ)。
全体の正解率0.840だけを見ると、問題なさそうに見えます。ところが、グループごとに分けると、グループBの正解率は0.730で、陰性の人を誤って陽性と判定する割合は、Aの約2.5倍(76人中25人)でした。
なぜ、こうなるのか
- 訓練データの9割がグループAなので、モデルは主にAの傾向に合わせて学習します
- Bでは特徴量と正解の関係が違うのに、Aに合わせた判定の仕方を当てはめられてしまいます
実際、グループBのデータだけで学習したモデルは、Bのテストデータで正解率0.920でした。Bの傾向は学べるのに、多数派Aの傾向に埋もれていたのです。
グループの情報を使わなくても、偏りは起きる
この実験のモデルは、グループの情報を一切使っていません。それでも偏りが起きました。「性別や年齢などの属性を特徴量から外せば、公平になる」とは限らない、ということです。さらに実際のデータでは、住んでいる地域や使っている言葉など、ほかの特徴量が属性と強く結び付いていて、属性を外しても、間接的に使われてしまうことがあります。
偏りを測り、減らす
まず、グループごとに測る
公平性の点検の第一歩は、評価指標をグループごとに分けて計算する ことです。正解率だけでなく、偽陽性率(誤って陽性と判定する割合)と偽陰性率(見逃す割合)も比べます。どちらの間違いが、どのグループに、どれくらい起きているかを見るためです。
「公平」の決め方は、1つではありません。例えば、
- グループごとの 正解率 をそろえる
- グループごとの 偽陽性率・偽陰性率 をそろえる(間違い方をそろえる)
- グループごとの 陽性と判定する割合 をそろえる
などの考え方があり、すべてを同時に満たすことは、多くの場合できないことが知られています。どれを大切にするかは、そのAIを何に使うかによって、人間が話し合って決める必要があります。
対策を試す
同じデータで、2つの対策を試しました。
- Bのデータを重く扱う: Bの正解率は上がりましたが、今度はAの正解率が下がりました(Aの見逃しの割合が0.168から0.329に増えた)。一方を改善すると、もう一方が悪くなることがあります
- グループの違いをモデルに組み込む(グループを表す印と、グループと特徴量の組み合わせを特徴量に加える): AもBもよくなり、偽陽性率もほぼそろいました
ただし、2つ目の方法は、グループを表す属性(性別・年齢など)をモデルに入力することになります。場面によっては、属性を判定に使うこと自体が、法律や社会のルールで制限されていたり、別の差別につながったりすることがあります。技術だけで決めず、使う場面のルールと、影響を受ける人々の立場を確かめて選ぶ 必要があります。
ほかにも、データを集め直して少数のグループのデータを増やす、グループごとにしきい値を見直す、といった方法があります。どの方法でも、対策の後に、もう一度グループごとに測り直して確かめます。
Pythonでグループごとに測る、よくある誤解と振り返り
グループを表す配列で、データを選び出してから、評価指標を計算します。
import numpy as np
y_true = np.array([1, 0, 0, 1, 0, 0, 1, 0])
y_pred = np.array([1, 0, 1, 1, 0, 1, 1, 1])
group = np.array(["A", "A", "A", "A", "B", "B", "B", "B"])
for g in ["A", "B"]:
k = group == g # そのグループのデータだけを選ぶ印
acc = np.mean(y_true[k] == y_pred[k]) # 正解率
neg = y_true[k] == 0 # 本当は陰性のデータ
fpr = np.mean(y_pred[k][neg] == 1) # 偽陽性率
print(g, "正解率", acc, "偽陽性率", round(fpr, 3))
# → A 正解率 0.75 偽陽性率 0.5
# → B 正解率 0.5 偽陽性率 0.667
group == g は、そのグループなら True の配列です。y_true[k] のように使うと、True の位置のデータだけを取り出せます(第3章の条件での取り出し)
- 偽陽性率は、「本当は陰性」のデータの中で、陽性と判定した割合です
よくある誤解
- 「全体の正解率が高ければ、どの人にも公平」: 全体0.840でも、少数のグループBでは誤判定が約2.5倍起きていました。グループごとに分けて測らないと見えません
- 「属性を特徴量から外せば、公平になる」: 実験のモデルは属性を使っていないのに偏りました。ほかの特徴量を通じて、間接的に偏ることもあります
- 「公平性は、1つの数字で決められる」: 正解率・間違い方・陽性と判定する割合など、公平の考え方はいくつもあり、同時にはそろえられないことが多いです。何を大切にするかは、使い方に合わせて人が決めます
振り返り
- 評価指標をグループごとに分けて計算し、正解率・偽陽性率・偽陰性率を比べる
- 少数のグループは、多数派の傾向に埋もれやすい。属性を使わなくても偏りは起きる
- 対策(重み付け、グループの違いの組み込み、データの追加など)にはそれぞれ副作用や制約がある。対策の後も、グループごとに測り直す