1. 問題と解答
AIにおける機械学習において,2クラス分類モデルの評価方法の一つであるROC曲線で用いられる偽陽性率の説明として,最も適切なものはどれか。ここで,分類されるデータには正しいものと間違っているものが含まれるものとする。
ア "間違い"と予測したデータのうち,実際は"正しい"データの割合
イ 実際に"間違い"であるデータに対し,誤って"正しい"と予測したデータの割合
ウ 実際に"間違い"であるデータに対し,正しく"間違い"と予測したデータの割合
エ 全データのうち,実際に正しく予測できなかったデータの割合
解答: イ
解答の考え方
偽陽性率(FPR)は「実際は Negative(間違い)であるデータのうち、誤って Positive(正しい)と予測された割合」。見分けるポイントは 分母が「実際のクラス」基準になっているか どうか。
| 選択肢 | 分母(母集団) | 分子 | 判定 |
|---|---|---|---|
| ア | 予測が「間違い」とされたデータ | そのうち実際は「正しい」 | 分母が予測結果基準 → FPRではない |
| イ | 実際が「間違い」のデータ | そのうち誤って「正しい」と予測 | 分母・分子とも条件一致 → FPR(正解) |
| ウ | 実際が「間違い」のデータ | そのうち正しく「間違い」と予測 | これはTNR(特異度)の定義 |
| エ | 全データ | そのうち予測を誤ったもの | これはError Rate(誤り率)の定義 |
ア・ウ・エはそれぞれ別の指標(分母が予測基準/特異度/誤り率)の定義になっており、正しく「実際のクラス=間違い」を分母に取っているイだけがFPRの定義と一致する。
2. 基礎概念と公式
2クラス分類(正しい/間違い、陽性/陰性)の結果は次の4パターンに分かれる。
| 実際 | 予測 | 名称 |
|---|---|---|
| 正しい | 正しい | TP(真陽性) |
| 正しい | 間違い | FN(偽陰性) |
| 間違い | 正しい | FP(偽陽性) |
| 間違い | 間違い | TN(真陰性) |
ここから作れる代表的な指標は以下の通り。
| 指標 | 公式 | 意味(実際の母集団を基準に) |
|---|---|---|
| TPR 真陽性率 / Recall / Sensitivity | TP / (TP + FN) |
実際が正のうち、正しく見つけられた割合 |
| FNR 偽陰性率 | FN / (TP + FN) |
実際が正のうち、見逃した割合 |
| TNR 真陰性率 / Specificity | TN / (TN + FP) |
実際が負のうち、正しく判定できた割合 |
| FPR 偽陽性率 | FP / (TN + FP) |
実際が負のうち、誤って正と判定した割合 |
| Precision 適合率 | TP / (TP + FP) |
正と予測したうち、実際に正だった割合 |
| NPV 陰性的中率 | TN / (TN + FN) |
負と予測したうち、実際に負だった割合 |
| Accuracy 正解率 | (TP + TN) / (TP + TN + FP + FN) |
全データのうち判定が正しかった割合 |
| Error Rate 誤り率 | (FP + FN) / (TP + TN + FP + FN) |
全データのうち判定を誤った割合 |
| F1-score | 2TP / (2TP + FP + FN) |
Precision と Recall の調和平均 |
覚えておくと便利な関係
TPRとFNRは「実際が正」という同じ母集団を分母にしているので、足すと必ず1になる。
TPR + FNR = TP/(TP+FN) + FN/(TP+FN) = 1
同様に、TNRとFPRは「実際が負」という同じ母集団が分母なので、これも足すと1になる。
TNR + FPR = TN/(TN+FP) + FP/(TN+FP) = 1
つまり FPR = 1 − TNR、FNR = 1 − TPR と言い換えられる。
ROC曲線はこのFPRとTPRを軸にとったグラフ:
横軸 = FPR = FP / (FP + TN)
縦軸 = TPR = TP / (TP + FN)
一言でまとめると、FPRは「実際に負である集団の中でどれだけ誤って正と判定したか」、TPRは「実際に正である集団の中でどれだけ正しく言い当てたか」 を表す指標。分母が常に「実際のクラス」であることさえ覚えれば、分母が予測結果基準になっている選択肢に惑わされずに済む。
3. 参考資料:ROC曲線とAUCのアニメーション
出典: ROC curve, AUCを視覚的に理解する animation付き (Qiita, @kenmatsu4)
コード全体: Gist: matsuken92/05c2bc24c9edf83334b0
しきい値と分類
検査数値のような1次元の値を使って「病気 / 健康」を判定する場面を考える。判定にはしきい値を1つ設定し、例えば「検査数値が27未満なら病気、27以上なら健康」のように分類する。元記事の数値例(しきい値27)を上の混同行列に当てはめると:
- TPR(真陽性率)= 0.909(病気の人の91%を正しく「病気」と判定)
- FNR(偽陰性率)= 0.091(残り9%の病気の人を誤って「健康」と判定)
- FPR(偽陽性率)= 0.280(健康な人の28%を誤って「病気」と判定)
- TNR(真陰性率)= 0.720(残り72%の健康な人を正しく「健康」と判定)
病気群・健康群それぞれの検査数値の分布(正規分布)を考えると、しきい値 x における
- TPR = 病気群の分布の累積分布関数(しきい値より「陽性側」の累積確率)
- FPR = 健康群の分布の累積分布関数(同上)
に対応する。つまり密度曲線を積分した累積分布曲線(CDF)の値そのものが TPR / FPR になる。
ROC曲線の描き方
しきい値を表す縦線(識別境界)を左から右へ動かしていくと、その位置ごとに (FPR, TPR) が1組決まる。この (FPR, TPR) を横軸=FPR, 縦軸=TPR の平面上にプロットし、しきい値を動かした軌跡を線でつなぐと ROC曲線 になる。
roc_curve_animation.py の「密度曲線・累積曲線・ROC曲線を同時表示」するアニメーション(1)は、まさにこの「動いている縦線 → 累積曲線上の点 → ROC曲線上の点」という対応関係を、静止画では伝わりにくい部分を動きで見せている。
AUC(Area Under the Curve)
ROC曲線の下側の面積を AUC と呼ぶ。
- 2群の分布が完全に分離している(判別が完璧)→ ROC曲線は左上の角に張り付き、AUC → 1
- 2群の分布が完全に重なっている(判別能力なし、ランダム判定と同じ)→ ROC曲線は対角線 y = x に一致し、AUC = 0.5
- 元記事の数値例では AUC ≈ 0.867953
何がAUCを決めるか
元記事は、2つの要因がAUC(=判別性能)を左右することをアニメーションで示している。
-
平均の差:2群の分布の平均が離れているほど重なりが減り、ROC曲線が左上にシフトしてAUCが上がる(アニメーション
2:平均 μ1 を 10→30 と動かして分布2の平均に近づける) -
分散の差:分布の広がり(標準偏差)が小さいほど重なりが減り、同様にAUCが上がる(アニメーション
3:標準偏差 σ1 を 5→0.5 と縮めていく)4は3と同じ動きにAUCの数値も表示したもの。
まとめると、2つの分布が「離れているか」「尖っているか(分散が小さいか)」がそのままROC曲線の形=判別性能を決める、というのがこの記事の核心的な主張。
アニメーション一覧
| # | 内容 | 何を動かすか |
|---|---|---|
| 1 | 密度曲線・累積曲線・ROC曲線を同時表示 | 判定しきい値 x |
| 2 | 分布1の平均が分布2に近づく | 平均 μ1 (10→30) |
| 3 | 分布1の分散が分布2に近づく | 標準偏差 σ1 (5→0.5) |
| 4 | 3と同じだが ROC曲線のタイトルに AUC を表示 | 標準偏差 σ1 + AUC値 |
ファイル構成
- roc_curve_animation.py — 上記4つのアニメーションを再現する実行可能スクリプト(元記事のコードを1本にまとめたもの)
実行方法
pip install matplotlib numpy scipy pillow
python roc_curve_animation.py 1 # output/ROC_curve1.gif
python roc_curve_animation.py 2 # output/ROC_curve2.gif
python roc_curve_animation.py 3 # output/ROC_curve3.gif
python roc_curve_animation.py 4 # output/ROC_curve_auc.gif
python roc_curve_animation.py all # 4つまとめて生成
output/ サブフォルダに .gif が出力される(動作確認済み。output/ 内の4つのgifは上記のREADME内プレビューにも使われているもの)。
元記事のコードからの変更点
元のコードをそのまま動かすには2つの外部依存があり、環境によっては動かないので置き換えた。
-
writer='imagemagick'→PillowWriter
元記事は GIF 保存に ImageMagick の外部バイナリを使用している。ImageMagick が未インストールの環境でも動くように、matplotlib 標準搭載のPillowWriter(Pillow ライブラリのみに依存)に変更。 -
sklearn.metrics.auc→numpy.trapz
AUC計算(アニメーション4)にscikit-learnを使っていたが、台形則によるAUC計算はnumpy.trapzだけで完結するため、scikit-learn依存を無くした。計算結果は同じ。
それ以外のロジック(分布のパラメータ、描画内容、フレーム数など)は元記事のまま。



