Python環境を起動中... 初回のみ数秒かかります
Lesson 8 / 12

分類モデルの評価

このレッスンで学ぶこと

  • 「正解率だけ」では危ない理由が分かる
  • 混同行列(TP・FP・FN・TN)を読める
  • 適合率・再現率・F1スコアの違いを説明できる
  • 医療で「偽陰性(見逃し)」が重い理由が分かる

1. 「正解率だけ」では危ない

前回、分類モデルの正解率(accuracy)は98%でした。高そうに見えます。でも—— 正解率は、ときに人をだます指標です。極端な例で確かめましょう。

ある病気の検査を考えます。1000人中、本当に病気なのは50人(5%)だけ。 ここで「全員を“健康”と判定するだけ」のいい加減なモデルを作るとどうなるでしょう?

sample_1.py
Ctrl+Enter
出力

⚠ これが「正解率の罠」: 何もしていないモデルが正解率95%。でも病気の人を1人も見つけられていません(再現率0%)。 データに偏り(病気が少数)があると、正解率は簡単に高く見えてしまうのです。 だから分類では、正解率以外の指標でモデルを多面的に評価します。

2. 混同行列

分類の結果を細かく見るための表が 混同行列(confusion matrix) です。 「実際」と「予測」を突き合わせ、4種類の結果に分けて数えます。 病気を「陽性(見つけたいもの)」とすると、次の4マスになります。

混同行列:TP・FN・FP・TN の4マスと偽陰性の重要性
混同行列の4マス。とくに FN(偽陰性=病気の見逃し)は医療で最も避けたい誤り
記号名前意味
TP真陽性病気の人を、正しく「病気」と判定(正解)
FN偽陰性病気の人を、誤って「健康」と判定(=見逃し)
FP偽陽性健康な人を、誤って「病気」と判定(=過剰な警告)
TN真陰性健康な人を、正しく「健康」と判定(正解)

実際のモデルで混同行列を出してみましょう。前回(レッスン7)とは逆に、ここでは見つけたい「悪性」を陽性(1)として扱います(医療では「見つけたい病気=陽性」と置くのが自然だからです)。

💡 y = (y0 == 0).astype(int) って何をしている?: 元データは「悪性=0 / 良性=1」。これを悪性=1(陽性)に置き換えるための1行です。2段階に分けると分かりやすいです。

  • y0 == 0 … 各患者が「悪性か?」を True / False の並びで表す(悪性ならTrue)
  • .astype(int) … その True / False1 / 0 に変換する(True→1、False→0)

結果、悪性だった人が1(陽性)、良性が0(陰性)になります。

sample_2.py
Ctrl+Enter
出力

🩺 このモデルは「見逃し」が1人: 悪性63人のうち、62人を正しく悪性と判定(TP)、1人を見逃した(FN)。 また、健康な人2人を誤って悪性と判定(FP)しています。 医療ではFN(見逃し)を限りなく減らしたい——たとえFP(過剰警告)が少し増えても、 病気を見逃すよりはマシ、と考えるのが基本です。

3. 適合率・再現率・F1スコア

混同行列の4マスから、3つの便利な指標が計算できます。どれも0〜1で、1に近いほど良いです。

指標意味(ざっくり)気にする場面
適合率
(precision)
「陽性」と予測したうち、本当に陽性だった割合誤検知(FP)を減らしたいとき
再現率
(recall)
本当の陽性のうち、見つけられた割合見逃し(FN)を減らしたいとき=医療で重視
F1スコア適合率と再現率のバランス両方を総合的に見たいとき

📐 式で書くと(混同行列の TP・FP・FN を使って):

  • 適合率(precision)TP ÷ (TP + FP) … 陽性と予測した中で本当に陽性だった割合
  • 再現率(recall)TP ÷ (TP + FN) … 実際の陽性の中で見つけられた割合
  • F1スコア2 × 適合率 × 再現率 ÷ (適合率 + 再現率) … 2つの調和平均(バランス)

分子はどちらも TP(正しく当てた陽性)。分母が「陽性と予測した数(適合率)」か「実際の陽性の数(再現率)」かの違いです。

sample_3.py
Ctrl+Enter
出力

💡 再現率0.984の意味: 本当の悪性63人のうち、98.4%(62人)を見つけられたということ。 残り1.6%(1人)が見逃し(FN)です。医療AIでは、この再現率(見逃さない力)を特に高くしたい場面が多いです。 ただし再現率を上げようとFPが増える(過剰警告が増える)こともあり、適合率とのバランス(F1)も見ます。

4. 練習問題

問題 1

混同行列を出して見逃しを数えよう

下記の実際予測(1=陽性)から混同行列を作り、表示してください。 その後、偽陰性(FN=見逃し)が何人かをヒントで確認しましょう。

exercise_1.py
出力
ヒントを見る(答え+解説)
from sklearn.metrics import confusion_matrix

y_true = [1, 1, 1, 0, 0, 1]
pred   = [1, 0, 1, 0, 1, 1]

print(confusion_matrix(y_true, pred))
# [[1 1]    ← 実際 陰性:1正解(TN), 1を陽性と誤り(FP)
#  [1 3]]   ← 実際 陽性:1を見逃し(FN), 3正解(TP)

混同行列は [[1, 1], [1, 3]]偽陰性(FN)は1人(右下より1つ左の値)。 実際は陽性だったのに「陰性」と予測してしまった人です。

問題 2

適合率・再現率・F1を計算しよう

問題1と同じデータで、適合率・再現率・F1スコアを計算して表示してください。

exercise_2.py
出力
ヒントを見る(答え+解説)
from sklearn.metrics import precision_score, recall_score, f1_score

y_true = [1, 1, 1, 0, 0, 1]
pred   = [1, 0, 1, 0, 1, 1]

# 適合率・再現率・F1 を表示してください
print("適合率:", round(precision_score(y_true, pred), 3))   # 0.75
print("再現率:", round(recall_score(y_true, pred), 3))      # 0.75
print("F1:", round(f1_score(y_true, pred), 3))             # 0.75

陽性予測4人のうち3人が正解 → 適合率0.75。実際の陽性4人のうち3人を発見 → 再現率0.75。 今回は両方0.75なのでF1も0.75になります。

問題 3

「正解率の罠」を体験しよう

陽性が10%(100人中10人)のデータで、「全員を陰性と予測」したときの正解率再現率を計算してください。 正解率は高いのに再現率はどうなるでしょう?

exercise_3.py
出力
ヒントを見る(答え+解説)
from sklearn.metrics import accuracy_score, recall_score

y_true = [0] * 90 + [1] * 10   # 100人中10人が陽性
pred   = [0] * 100             # 全員を陰性と予測

# 正解率と再現率を表示してください
print("正解率:", accuracy_score(y_true, pred))   # 0.9
print("再現率:", recall_score(y_true, pred))     # 0.0

正解率は 0.9(90%)と高いのに、再現率は 0.0。陽性の人を1人も見つけられていません。 正解率が高い=良いモデル、とは限らない。とくに偏ったデータでは、再現率など複数の指標で確認することが大切です。

5. まとめ

このレッスンのポイント

  • 偏ったデータでは正解率(accuracy)は当てにならない(正解率の罠)
  • 混同行列で TP・FP・FN(見逃し)・TN の4種類に分けて見る
  • 適合率=陽性予測の正しさ/再現率=陽性の見つけ率(見逃しの少なさ)
  • F1スコア=適合率と再現率のバランス
  • 医療ではFN(偽陰性=見逃し)を減らす=再現率を高めるのが特に重要

自由に試してみましょう:

free_practice.py
出力

💡 classification_report の表に出る見慣れない言葉(軽く知っておけばOK): 各区分(良性/悪性)ごとに precision・recall・f1-score が並びます。それに加えて——

  • support … その区分の件数(テストに何人いたか)
  • macro avg … 各区分の指標の単純平均
  • weighted avg … 件数(support)で重みづけした平均

いまは「そういう要約の行も出るんだな」程度の理解で大丈夫です。

完了するとコース一覧に進捗が記録されます