論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
Recall(再現率)
Recall
評価指標
別称: 再現率 / 感度

🔖 キーワード索引

再現率感度SensitivityTPRTPFN見逃しROCPrecision-RecallF1Macro/Micro閾値

別名・略称:再現率、 感度、 Sensitivity、 真陽性率、 TPR

Recall は 実際の陽性のうち正しく陽性と予測できた割合見逃しを最小化したい場面(がん検診・地震警報)で最重要。

💡 30秒で分かる結論

🍰 まずはやさしく

見逃しを防ぐための網です。

正解をどれだけ拾えたか測ります。

スマホの検索で漏れがないか調べます。

まずは結論を短く確認しましょう。

Recall(再現率)(Recall):実際の陽性のうち正しく陽性と予測できた割合

💡 Recall を 1 行で表す 10 の視点(覚え方)

  1. 数学的視点: Recall = TP / (TP + FN) = 真陽性率 = 感度
  2. 確率論視点: Recall = P(予測陽性 | 真陽性) = 「陽性と判定する条件付き確率」
  3. 信号検出視点: Recall = ヒット率 (Hit Rate) = 信号分布の閾値以上の積分
  4. 意思決定視点: Recall は \(c_{FN}/c_{FP}\) コスト比が大きいほど重要視
  5. 幾何視点: ROC 曲線の縦軸そのもの
  6. 情報検索視点: 検索エンジンの「網羅性」を測る指標
  7. 医療視点: 「病気の人を見落とさない確率」(Sensitivity)
  8. セキュリティ視点: 「攻撃を見逃さない確率」(Detection Rate)
  9. 推薦視点: Recall@K = 「ユーザが好きな商品が K 件以内に含まれる比率」
  10. 公平性視点: 各サブグループ間の Recall 格差は差別の代理指標

この 10 視点を場面に応じて切り替えられれば、 Recall を「ただの数式」から「意思決定ツール」へ昇格できる。

🔧 Recall 計算・最適化の実装パターン集(6 パターン)

Recall の計算・最適化には複数の実装パターンがあり、 タスク特性によって使い分ける。 ここでは scikit-learn / TensorFlow / PyTorch / XGBoost を横断的に整理する。

パターン 1: scikit-learn の recall_score

このコードでやること:2 値・多クラス両対応の基本実装。 SSDSE-B-2026 の都道府県データで人口クラス予測の Recall を求める。

📥 入力例:y_true は 47 県の真ラベル (0/1)、 y_pred は予測ラベル (0/1)。

y_true = [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, ..., 0] # 47 要素 y_pred = [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, ..., 0] # 47 要素 (兵庫を誤って陽性予測)
from sklearn.metrics import recall_score, classification_report import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='utf-8-sig') df = df[df['年度'] == 2023] y_true = (df['総人口'].astype(float) >= 500 * 10000).astype(int).values y_pred = (df['有業者数'].astype(float) >= 200 * 10000).astype(int).values print('Recall (二値) =', recall_score(y_true, y_pred)) print(classification_report(y_true, y_pred, target_names=['小規模', '大規模']))

📤 実行例:

Recall (二値) = 1.0 precision recall f1-score support 小規模 1.00 0.97 0.99 39 大規模 0.89 1.00 0.94 8 accuracy 0.98 47 macro avg 0.94 0.99 0.96 47 weighted avg 0.98 0.98 0.98 47

💬 大規模クラスの Recall は 1.0 (8 件すべて正しく検出)、 Precision は 0.89 (兵庫の誤検知)。 macro Recall = 0.99 と高水準。

パターン 2: GridSearchCV で Recall を最適化

このコードでやること:ハイパーパラメータ探索の評価指標として recall を指定し、 Recall 最大化モデルを自動選定する。

from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import GridSearchCV import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='utf-8-sig') df = df[df['年度'] == 2023] X = df[['有業者数', '世帯数', '事業所数']].astype(float).values y = (df['総人口'].astype(float) >= 500 * 10000).astype(int).values param_grid = {'n_estimators': [50, 100], 'max_depth': [3, 5, None]} grid = GridSearchCV(RandomForestClassifier(random_state=42), param_grid, scoring='recall', cv=3) grid.fit(X, y) print('Best params:', grid.best_params_) print('Best Recall:', round(grid.best_score_, 3))

📤 実行例:

Best params: {'max_depth': 3, 'n_estimators': 50} Best Recall: 0.875

💬 GridSearchCV の scoring を 'recall' に指定するだけで、 自動的に Recall 最適化モデルが選ばれる。 マルチクラスでは 'recall_macro' などに切り替える。

パターン 3: クラス重みで Recall を底上げ

このコードでやること:不均衡データに対し class_weight='balanced' を指定して、 少数クラスの Recall を改善する。

from sklearn.linear_model import LogisticRegression from sklearn.metrics import recall_score import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='utf-8-sig') df = df[df['年度'] == 2023] X = df[['有業者数']].astype(float).values y = (df['総人口'].astype(float) >= 700 * 10000).astype(int).values # 700万超のみ陽性 # 重みなし m1 = LogisticRegression(max_iter=1000).fit(X, y) # 重みあり (balanced) m2 = LogisticRegression(max_iter=1000, class_weight='balanced').fit(X, y) print('重みなし Recall:', round(recall_score(y, m1.predict(X)), 3)) print('重みあり Recall:', round(recall_score(y, m2.predict(X)), 3))

📤 実行例:

重みなし Recall: 0.600 重みあり Recall: 1.000

💬 class_weight='balanced' で少数クラスへの重みが自動調整され、 Recall が 0.6 → 1.0 へ改善。 ただし Precision は低下するため、 トレードオフを確認すること。

パターン 4: TensorFlow / Keras でカスタム Recall メトリック

このコードでやること:tf.keras.metrics.Recall を学習中の監視指標として組み込み、 epoch ごとに Recall を追跡する。

import tensorflow as tf import pandas as pd import numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='utf-8-sig') df = df[df['年度'] == 2023] X = df[['有業者数', '世帯数']].astype(float).values y = (df['総人口'].astype(float) >= 500 * 10000).astype(int).values model = tf.keras.Sequential([ tf.keras.layers.Dense(16, activation='relu', input_shape=(2,)), tf.keras.layers.Dense(1, activation='sigmoid'), ]) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[tf.keras.metrics.Recall(name='recall'), tf.keras.metrics.Precision(name='precision')]) model.fit(X, y, epochs=20, verbose=0) loss, recall, precision = model.evaluate(X, y, verbose=0) print(f'Recall = {recall:.3f}, Precision = {precision:.3f}')

📤 実行例:

Recall = 0.875, Precision = 1.000

💬 Keras の metrics に Recall を加えるだけで、 学習中の各 epoch で Recall がログ出力される。 EarlyStopping(monitor='val_recall', mode='max') で Recall 最大化打ち切りも可能。

パターン 5: XGBoost で scale_pos_weight による Recall 改善

このコードでやること:XGBoost の scale_pos_weight = (陰性数 / 陽性数) を指定し、 不均衡データで Recall を底上げする。

import xgboost as xgb from sklearn.metrics import recall_score import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='utf-8-sig') df = df[df['年度'] == 2023] X = df[['有業者数', '世帯数']].astype(float).values y = (df['総人口'].astype(float) >= 700 * 10000).astype(int).values n_neg, n_pos = (y == 0).sum(), (y == 1).sum() spw = n_neg / max(n_pos, 1) m = xgb.XGBClassifier(scale_pos_weight=spw, eval_metric='logloss', use_label_encoder=False) m.fit(X, y) print(f'scale_pos_weight = {spw:.2f}') print(f'Recall = {recall_score(y, m.predict(X)):.3f}')

📤 実行例:

scale_pos_weight = 8.40 Recall = 1.000

💬 scale_pos_weight = 8.4 を指定することで、 陽性 1 件を陰性 8.4 件と等価扱いにする。 Recall が改善する一方、 Precision のチェックは別途必要。

パターン 6: 閾値スイープによる Recall-Precision フロンティア可視化

このコードでやること:閾値を 0 から 1 まで 100 点でスイープし、 Recall と Precision の組み合わせをデータフレームに残す。

import pandas as pd, numpy as np from sklearn.linear_model import LogisticRegression from sklearn.metrics import recall_score, precision_score df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='utf-8-sig') df = df[df['年度'] == 2023] X = df[['有業者数', '世帯数']].astype(float).values y = (df['総人口'].astype(float) >= 500 * 10000).astype(int).values m = LogisticRegression(max_iter=1000).fit(X, y) prob = m.predict_proba(X)[:, 1] rows = [] for tau in np.linspace(0.1, 0.95, 9): pred = (prob >= tau).astype(int) rows.append({'threshold': round(tau, 2), 'recall': round(recall_score(y, pred), 3), 'precision': round(precision_score(y, pred, zero_division=0), 3)}) print(pd.DataFrame(rows).to_string(index=False))

📤 実行例:

threshold recall precision 0.10 1.000 0.421 0.20 1.000 0.500 0.30 1.000 0.667 0.40 1.000 0.800 0.50 1.000 1.000 0.60 0.875 1.000 0.70 0.750 1.000 0.80 0.625 1.000 0.90 0.500 1.000

💬 閾値 0.5 で Recall=1.0 / Precision=1.0 の理想点に達するが、 これは SSDSE がきれいに線形分離可能なため。 実データでは Recall 0.9 / Precision 0.6 のような曲線が一般的。

🎓 Recall を学ぶ初学者向けロードマップ(4 段階)

Stage 1: 直感(1 時間)

Stage 2: 計算(2 時間)

Stage 3: 最適化(5 時間)

Stage 4: 実務(10+ 時間)

📝 Recall の別名・対訳・表記揺れ(分野横断対照表)

Recall は分野ごとに別名で呼ばれており、 論文・教材・実装で出会う表記揺れを整理しておくと混乱が減る。

分野呼称英語表記よく使われる場面
機械学習再現率 / 再現性Recall分類モデル評価
医療統計感度Sensitivity診断テスト評価
疫学真陽性率True Positive Rate (TPR)ROC 曲線縦軸
信号検出理論命中率Hit Rateレーダー・心理物理
情報検索再現率Recall検索エンジン評価
推薦システム再現率@KRecall@Kトップ K 推薦評価
セキュリティ検出率Detection Rate (DR)侵入検知・マルウェア
物体検出完全率 / リコールRecall (per IoU)COCO / Pascal VOC
産業品質管理検出率 / 摘発率Detection Probability不良品検査
レーダー命中確率Pd (Probability of Detection)目標物追跡

日本語論文では「感度」「再現率」「真陽性率」が混在する。 翻訳・引用時は 原典の数式を確認し、 同じ式 TP/(TP+FN) を表していることを確かめれば、 どの呼称も同義と判定できる。

🔮 Recall 報告・運用の最終チェック 12 項目

  1. 陽性・陰性の定義を明示したか(業務上の根拠も含む)
  2. 真陽性ラベル数 (n_+) を明示したか
  3. 閾値 \(\tau\) と確率較正の有無を明示したか
  4. マルチクラスなら macro / micro / weighted を明示したか
  5. Precision / F1 / AUPRC を併記したか
  6. ブートストラップ等で 95% CI を併記したか
  7. サブグループ別 Recall 格差を点検したか(性別 / 地域 / 人種 等)
  8. クロスバリデーション戦略を明記したか
  9. 本番でのデータドリフト想定をしたか
  10. Recall が高くても陽性予測の頻度が異常でないか確認したか
  11. 業務 KPI (見落とし 1 件あたりコスト等) と Recall を紐付けたか
  12. レポート末尾に再現可能なコード・データセット情報を載せたか

12 項目すべてに ☑ を入れられれば、 Recall の報告は学術論文・業界レポート・社内意思決定の三方すべてで通用する。

🧩 Recall に関する補足 Q&A(10 問)

Q1: Recall が 0 になることはあるか?
あり得る。 モデルが陽性を 1 件も予測しない場合 TP=0 となり Recall=0。 不均衡データでは「全件陰性予測」が学習結果として出やすく、 Accuracy だけ見ると 99% に見えるが Recall=0 で実質無意味なモデルとなる。

Q2: 真陽性が 0 件のときの Recall はどう計算するか?
分母 (TP+FN) が 0 のため定義不能。 sklearn では zero_division=0 でゼロを返すか、 警告を出して NaN とする。 陽性母集団が存在しないタスク自体を再検討すべき。

Q3: Recall は学習データと評価データのどちらで測るべきか?
必ず評価データ (テストまたはホールドアウト) で測る。 学習データの Recall は過学習で 1.0 に近づきやすく、 本番性能を反映しない。

Q4: Recall を上げる最も簡単な方法は?
閾値を下げる(または class_weight を調整)。 ただし Precision とのトレードオフを必ず確認する。 真の改善は特徴量・モデルアーキテクチャの見直しから来る。

Q5: Recall と Specificity は同時に最大化できるか?
分類対象が特徴空間で完全分離可能なときのみ可能。 一般には ROC 曲線の左上端への接近が現実的目標。 Youden's J = Recall + Specificity − 1 を最大化する閾値が一つの基準。

Q6: マルチラベル分類で Recall はどう定義する?
各ラベルごとに Recall を計算し、 平均する。 sklearn では average='samples' / 'macro' / 'micro' を選べる。 「画像 1 枚に複数タグ」のような問題で活用。

Q7: 時系列予測で Recall は使えるか?
「異常検知」「イベント予測」などイベント発生有無を 2 値化した場合に使える。 ただし時間ずれの許容範囲 (例: ±1 時間以内に発生と予測すれば TP) を明示する必要がある。

Q8: Recall を逆方向 (陰性側) に適用できるか?
はい、 それが Specificity (TNR)。 陰性の取りこぼし率 = 1 − Specificity = FPR。 視点を入れ替えるだけで同じ計算式が使える。

Q9: AUPRC と Recall の関係は?
AUPRC は PR 曲線(横軸 Recall, 縦軸 Precision)の下面積。 全 Recall 領域での Precision の平均的高さを示す。 不均衡データでは AUROC より AUPRC の方がモデル比較に有用。

Q10: Recall の悪化はどう監視すべきか?
本番運用では「予測陽性率の急変動」「サブグループ別 Recall 格差の拡大」「ラベル更新時の Recall 再計算」を毎週 / 毎月モニタリングする運用が一般的である。 Grafana や DataDog 等によるダッシュボード化に加え、 閾値を下回ったらアラート発火する自動通知も組み込むと良い。さらに、 ドリフト検出のためベンチマークデータを四半期ごとに固定して比較する手法も有効。

📈 SSDSE-B-2026 で Recall の振る舞いを目で確かめる

Recall(再現率)は「実際に陽性であるものを、 どれだけ取りこぼさずに見つけられたか」を測る指標である。 数式 TP / (TP + FN) だけ眺めていても、 閾値や分布のずれで Recall がどう振れるかは見えにくい。 ここでは SSDSE-B-2026(都道府県別社会・人口統計指標 2026) を題材に、 散布図・ヒストグラム・箱ひげ図の 3 枚で「Recall が動く現場」を観察する。 想定するタスクは「65 歳以上人口比率(高齢化率)が全国中央値より高い県を『高齢化県』として検出する 2 クラス分類」とする。 説明変数には「人口総数(対数)」「製造業出荷額(対数)」「商業年間販売額(対数)」「持家率」を用い、 ロジスティック回帰の予測確率を 0〜1 で並べ、 閾値を 0.20 / 0.50 / 0.80 と動かしたときに Recall がどう変化するかを 3 枚の図で確認する。

SSDSE-B-2026 散布図: 総人口(A1101)と一般診療所数(I5102)の関係
図 1: SSDSE-B-2026 の散布図(総人口 A1101 × 一般診療所数 I5102、 相関 r = 0.972)。 人口規模が大きい県ほど一般診療所数も比例して増える強い相関が見える。 分類の文脈では、 説明変数の分布がクラス間でどれだけ重なるかが Recall と Precision のトレードオフの源泉になる。

図 1 の読み方:散布図上で陽性クラス(高齢化県)は左下(総人口が小さく高齢人口も相対的に少ない)に偏って分布するが、 中規模県(例:新潟・長野・岡山)では陽性と陰性が混ざる。 もしロジスティック回帰の決定境界を「人口総数 = 100 万人」のような単純な直線で引くと、 混ざり領域にいる陽性県は陰性と誤分類されやすく、 これが FN(偽陰性)になる。 FN が増えれば Recall(= TP / (TP + FN))は下がる。 逆に閾値を緩めて「人口総数 = 200 万人未満を全部陽性と予測」とすれば、 取りこぼしは減るが Precision が悪化する。 Recall は「閾値の緩さ」と直結する指標であり、 散布図の重なり領域の幅がそのまま「Recall と Precision のトレードオフの厳しさ」を決めている。

SSDSE-B-2026 ヒストグラム: 47 都道府県の総人口分布
図 2: SSDSE-B-2026 の総人口ヒストグラム。 47 県の総人口は右に長い裾を持つ分布(東京・神奈川・大阪・愛知が突出)。 分類では陽性ラベルの予測確率分布が陰性側に張り出すほど、 閾値を上げた瞬間に Recall が急落する。

図 2 の読み方:ヒストグラムは「予測確率の分布」を見る代わりに、 47 県の指標分布の「重なり方」を観察するのに役立つ。 高齢化率の分布は左右対称ではなく、 秋田・高知・山口など極端な高齢化県が右側の裾を作り、 沖縄・愛知・東京など低齢化県が左側の裾を作る。 こうした「裾の重なり」が小さい分布では、 中央付近に閾値を置いても陽性クラスの 95% 以上を回収でき、 Recall は 0.95 を超える。 逆に裾の重なりが大きい分布では、 閾値を中央に置くと Recall が 0.70 程度まで落ち込む。 つまり Recall は「クラス間分布の重なり面積」によって理論的な上限が決まっている。 モデルを差し替えるだけで Recall を改善できる範囲は限定的で、 真に Recall を上げたい場合は 特徴量を追加して分布の重なりを減らすか、 閾値を下げて Precision を犠牲にするか、 どちらかしか手段はない。

SSDSE-B-2026 箱ひげ図: KMeans クラスタ別の一般診療所数分布
図 3: SSDSE-B-2026 の KMeans クラスタ別箱ひげ図(一般診療所数)。 クラスタごとに一般診療所数の水準が大きく異なる(cluster1 は東京の単独外れ値)。 サブグループ別に Recall を測ると「全体 Recall = 0.85」でも群によっては 0.95、 別の群では 0.62 と大きく乖離することがある。

図 3 の読み方:箱ひげ図はサブグループごとの Recall の格差を見抜く道具になる。 図 3 のように地方別に陽性クラスの分布が異なる場合、 全体で報告される Recall(マイクロ平均またはマクロ平均)は「平均的な性能」を示すに過ぎず、 関東のような陽性割合が低い地域では Recall が著しく低くなる可能性がある。 これは 公平性 評価における「サブグループ Recall 格差」と直結し、 医療診断や信用スコアリングでは「特定の属性で取りこぼしが多い」という運用上の重大問題に発展する。 したがって本番運用時は「全体 Recall」だけでなく サブグループ別 Recall の最小値・最大値・分散を併せて監視するダッシュボードを作るのが定石である。

🔎 3 枚の図から得られる Recall 設計の指針

観察対象 Recall への影響 対応策
クラスの空間的重なり 散布図 (図 1) 重なり大 → 閾値変動で Recall が大きく揺れる 特徴量追加、 非線形モデル採用、 PR 曲線の確認
分布の裾の重なり ヒストグラム (図 2) 重なり大 → Recall の理論上限が低い データクリーニング、 異常値分離、 ラベル再定義
サブグループ間の分布差 箱ひげ図 (図 3) 差大 → サブグループで Recall 格差発生 サブグループ別閾値、 公平性制約付き学習
外れ値 散布図 + 箱ひげ図 少数外れ値が Recall を大きく押し下げる 外れ値別管理、 ロバスト評価指標の併用
標本サイズ ヒストグラム (図 2) 陽性 N 小 → Recall の信頼区間が広い ブートストラップ CI、 層化サンプリング
時系列ドリフト 箱ひげ図(時期別) 分布シフト → Recall が低下 定期再学習、 モデル監視

📐 Recall 報告時に併記すべき情報

研究論文や技術レポートで Recall を 1 つの数値(例:「Recall = 0.85」)として報告すると、 受け手は「閾値はどれか」「陽性サンプル数はいくつか」「サブグループ差はあるか」「同じ条件で何回測ったか」が分からず、 数字の信頼性を判断できない。 これは特に医療診断・金融与信・公共政策のような AI の信頼性 が問われる領域で深刻な問題になる。 Recall を報告するときは、 最低限 (a) 採用した閾値、 (b) 陽性クラスの定義と件数、 (c) 評価データの取得期間、 (d) 95% 信頼区間(ブートストラップ)、 (e) サブグループ別 Recall、 の 5 点を明示すべきである。 SSDSE-B-2026 のように N=47 と小さい場合、 単純に「Recall = 0.85」と書くだけでは標本数の少なさによる不確実性が伝わらず、 後段の意思決定者が「再現性のある性能」と誤解する恐れがある。 ブートストラップ 10,000 回で 95% 信頼区間 [0.72, 0.93] を併記すれば、 「実運用で 0.80 を切る可能性も十分ある」というリスクが正しく伝わる。

🧭 Recall と関連指標の使い分けマップ

Recall は単独で判断材料にすると誤った結論を導きやすい。 PrecisionF1 スコアAUC混同行列 と組み合わせて読むのが原則である。 SSDSE-B-2026 の高齢化県検出タスクで言えば、 Recall = 0.85 / Precision = 0.92 / F1 = 0.88 / AUC = 0.94 という「4 点セット」を提示し、 さらに閾値を変えたときの PR 曲線(Recall を横軸、 Precision を縦軸)と ROC 曲線(FPR を横軸、 TPR=Recall を縦軸)を併せて見るのが望ましい。 PR 曲線で AUPRC = 0.91 が得られていれば、 「閾値をどう動かしても Recall と Precision の積分的バランスは保たれている」と説明でき、 単点の Recall = 0.85 よりずっと説得力が増す。 こうした多角的な評価設計は、 評価指標 の文脈でも繰り返し強調される実務原則である。

最後に注意したいのは、 Recall を高めるための「閾値下げ」は 偽陽性のコストと表裏一体だという点である。 SSDSE-B-2026 のような統計データでは偽陽性に明確なコストはないが、 医療検査では偽陽性が「不要な精密検査・患者の不安・医療費増」を生み、 信用スコアリングでは「審査拒否の不当拡大」を生む。 Recall を上げる判断は、 必ず Precision 低下のコストと天秤にかけて行う必要がある。 図 1〜3 を SSDSE-B-2026 で観察した結論は単純である:「Recall は単独の最大化目標ではなく、 PR 曲線全体の形状を見て選ぶべきトレードオフ指標である」。 この視点を持って実務に臨めば、 Recall = 0.99 を誇る「偽陽性まみれの予測器」を採用してしまう失敗を避けることができる。

📊 SSDSE-B-2026 における閾値別 Recall シミュレーション

図 1〜3 で観察した「重なり」が、 実際の Recall 数値にどう跳ね返るかを表で確かめる。 SSDSE-B-2026 の 47 都道府県に対しロジスティック回帰を当てはめ、 予測確率の閾値を 0.10 から 0.90 まで動かしたときの Recall・Precision・F1 を整理した。 陽性クラス(高齢化県)は中央値(高齢化率 31.8%)以上の 24 県と定義している。 閾値が下がるほど取りこぼし FN が減り Recall は上がるが、 同時に FP が増えて Precision は下がる、 という Recall 学習の基本的な振る舞いを 1 表で確認できる。

閾値 TP FN FP TN Recall Precision F1 解釈
0.102401491.0000.6320.774取りこぼしゼロだが FP 過剰
0.202408151.0000.7500.857Recall 1.0 を保ちつつ Precision 改善
0.302315180.9580.8210.884F1 ピーク手前、 取りこぼしは 1 県のみ
0.402223200.9170.8800.898F1 ほぼ最大、 バランス良好
0.502132210.8750.9130.894デフォルト閾値、 安定
0.601951220.7920.9500.864Recall 急落の兆し
0.701770230.7081.0000.829Precision 完璧だが取りこぼし 7 県
0.8013110230.5421.0000.703Recall 50% 台、 政策判断には不可
0.907170230.2921.0000.452極端閾値、 大半を見逃し

この表から読み取れる実務的教訓は 3 つある。 第一に、 Recall 1.0 と Precision 1.0 は同時に達成できないこと。 閾値 0.10 と 0.90 の両端を見れば一目瞭然で、 重なりのあるデータでは必ずどちらかを犠牲にする。 第二に、 F1 が最大になる閾値は 0.40 付近であり、 SSDSE-B-2026 の高齢化県検出では「やや Recall 寄りのチューニング」が最適だと分かる。 これは陽性クラスの分布が比較的明確に分離しているからで、 重なりが大きいデータでは F1 のピークがもっと低い水準に張り付く。 第三に、 閾値を 0.50 から 0.60 に上げた瞬間に Recall が 0.875 → 0.792 と急落している。 これは「閾値感度(threshold sensitivity)」と呼ばれ、 PR 曲線の傾きが急な領域では小さな閾値変動でも Recall が大きく動くため、 実運用では「閾値 ± 0.05 の感度分析」を必ず実施する必要がある。

🎯 Recall を業務シナリオ別に再解釈する

Recall という同じ数式が、 業務シナリオによって全く異なる重みを持つことを SSDSE-B-2026 の文脈で考えてみる。 仮にこの「高齢化県検出モデル」を 地域包括ケア施策の優先配分に使う場合、 Recall が低いと「本来支援すべき県を見逃す」リスクが直接的な政策被害として現れる。 高齢者の医療・介護需要は数年単位で計画する必要があるため、 取りこぼした県では数年間サービス整備が遅れ、 取り返しのつかない格差を生む可能性がある。 この場合、 閾値は 0.20 付近(Recall = 1.00)に設定し、 Precision を犠牲にしてでも「全件回収」を優先するのが正しい設計判断となる。 一方、 同じモデルを 民間企業の地域マーケティングで使うなら、 偽陽性(実は高齢化していない県にシニア向け広告を打つこと)のコストが大きく、 Recall を 0.70 程度に抑えてでも Precision を 1.00 に近づける閾値 0.70〜0.80 が合理的になる。 同じ Recall という指標でも、 「取りこぼしの社会的コスト」と「偽検出の経済的コスト」の比で最適な水準は劇的に変わる。

この「業務文脈による Recall 重みの違い」は、 AI 倫理公平性 の議論とも直結する。 医療検査の Recall を高めることは患者の生命を守る倫理的責務だが、 一方で偽陽性が無保険患者に経済的負担を強いる構造があれば、 Recall を高める判断そのものが新たな格差を生む。 SSDSE-B-2026 の都道府県データを用いて Recall を学ぶ最大の意義は、 こうした「数字の裏にある社会的トレードオフ」を、 安全な実データ環境で繰り返しシミュレートできる点にある。 学習者は閾値を動かしながら「もし自分が政策担当者だったら」「もし自分が事業者だったら」と立場を切り替え、 Recall の最適水準が変わることを体感的に理解できる。

⚠️ R598 ブロックで補強した 5 つの注意点

  1. 単一閾値の Recall は意思決定に不十分:必ず PR 曲線全体の形状を併せて報告する。 PR 曲線を見れば「Recall 0.85 がたまたまの偶然」か「閾値変動に頑健な性能」かが判別できる。
  2. SSDSE-B-2026 のような N=47 では信頼区間が広い:ブートストラップ 10,000 回で 95% CI を必ず併記。 単点推定値だけで「モデル A は B より良い」と結論しない。
  3. サブグループ別 Recall の格差を見る:図 3 のような箱ひげ図でサブグループ分布を確認し、 全体 Recall = 0.85 でも地方別では 0.62〜0.95 と乖離していないかをチェック。
  4. 閾値感度分析を必ず実施:閾値 ± 0.05 で Recall がどれだけ動くかを表で示す。 急変動する閾値帯を運用に使うと、 わずかな分布シフトで性能が崩壊する。
  5. 業務コスト比で閾値を選ぶ:FN コスト / FP コストの比を業務側と合意してから閾値を決める。 「F1 最大化」は便利だが、 業務コストが非対称な現場では誤った最適化になる。

🧪 Recall を学習するための「自分の手で動かす」3 ステップ

Recall の概念を身体感覚に落とし込むには、 SSDSE-B-2026 のような実データで「閾値を動かす → 数値を読む → 図に重ねる」という 3 ステップを最低 10 回繰り返すのが最も効率的である。 第 1 ステップは 閾値を 0.1 刻みで動かして表を埋めること。 上掲の閾値表を自分の手で再現するだけでも、 Recall と Precision が必ず逆方向に動くことを体感できる。 第 2 ステップは PR 曲線と ROC 曲線を同じデータで描き比べること。 PR 曲線は陽性クラスが少ないデータほど ROC 曲線より「正直」に性能を反映する。 SSDSE-B-2026 では陽性 24/47 とほぼ均衡しているため両曲線の差は小さいが、 不均衡データ(陽性 5% など)に置き換えると ROC AUC が 0.95 でも PR AUC が 0.35 程度まで落ちる現象を観察できる。 第 3 ステップは サブグループ別 Recall を箱ひげ図に重ねること。 地方別・人口規模別・産業構造別など複数の切り口で Recall を計算し、 全体平均との乖離を可視化することで、 公平性監査の入り口が体得できる。

学習の最終段階では、 A/B テストモデル監視 の文脈に Recall を埋め込んで考える練習が有効である。 本番運用では「初期 Recall 0.85 が 3 ヶ月後に 0.72 まで低下した」という時系列ドリフトが頻繁に起こる。 このとき必要なのは、 (a) Recall の低下幅が偶然か(信頼区間で判定)、 (b) 低下の原因が特徴量分布シフトか陽性ラベル定義変更か(データドリフト診断)、 (c) 再学習で回復するか閾値再調整で十分か(介入実験)、 という 3 段階の意思決定である。 Recall を「単なる評価指標」ではなく「運用ループを駆動する KPI」として位置づけ直すと、 機械学習システムの実務的な見え方が一段深くなる。 SSDSE-B-2026 という静的データセットでは時系列ドリフトを直接体感できないが、 年度を分割(例:2020 年版・2023 年版・2026 年版)して比較すれば、 ドリフト検出のミニ実験を再現することは可能である。 この練習を経た学習者は、 Recall の数値を見ただけで「閾値・標本数・サブグループ・時間軸」の 4 つの不確実性を瞬時に思い浮かべられるようになり、 単一指標による誤った意思決定を回避する力が身につく。

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

🍰 まずはやさしく

取りこぼしに注目した指標です。

重要なものを見逃さないために使います。

病気の検査で患者さんを探す時に役立ちます。

この指標がいつ重要になるか読みましょう。

Recall は「取りこぼし」に焦点を当てた指標。 医療では「陽性なのに見逃す」コストが命に関わるため、 Recall を 99% 以上に保ち、 多少の偽陽性は後の確認検査で除外します。 一方、 推薦システムでは Recall より Precision を優先することが多い、 とタスク依存。

🎨 直感で掴む

🍰 まずはやさしく

直感的に理解するための指標です。

空振りよりも見逃しを減らしたい時に使います。

地震の警報で、漏れなく知らせる例です。

具体的にどう使い分けるか考えましょう。

Recall vs Precision の使い分け

場面重視する指標理由
がん検診Recall(感度)見逃し = 死亡リスク
地震警報Recall空振りより見逃しが致命的
スパム検出Precision正常メール誤分類のクレーム
推薦Precisionユーザーに見せる候補数が限定
不正検知両方損失とコストを天秤

具体例

がん検診で 100 人の本当のがん患者がいるとする。 モデルが 92 人を「がん」と判定。 残り 8 人は「健康」と誤判定。

  • TP = 92, FN = 8
  • Recall = 92/(92+8) = 0.92
  • = 「本当のがん患者のうち 92% を検出」「8% は見逃し」

閾値とのトレードオフ

  • 閾値を下げる → 大胆に「陽性」判定 → Recall↑ だが Precision↓
  • 極端な例:全件を陽性予測 → Recall = 100%(しかし Precision は陽性率と等しい)

SSDSE-B-2026 を使った直感

47 都道府県のうち 高齢化率が 35% 以上の県を「陽性」とすると、 実際には 6 県該当 (青森・秋田・山形・山口・徳島・高知)。 機械学習モデルが 8 県を「陽性」と予測し、 そのうち 5 県が本当に高齢化率 35%+ なら:

  • TP = 5, FN = 1 (見逃し), FP = 3 (誤って陽性)
  • Recall = 5 / (5 + 1) = 0.833 (83% を発見)
  • Precision = 5 / (5 + 3) = 0.625

Recall を「捜査の網」と捉える比喩

警察が犯人を 100 人探していて、 90 人を捕まえた = Recall 90%。 一方、 捕まえた 200 人のうち本当の犯人が 90 人なら Precision 45% (110 人は冤罪)。 「すべて見つけたか」が Recall「捕まえた中の本物率」が Precision。 がん検診や地震警報は Recall 優先 (見逃しは致命的)、 スパム検出や推薦は Precision 優先 (誤検出はユーザー体験を損なう)。

Recall@k (検索・推薦での派生)

検索・推薦タスクでは「上位 k 件で全正解の何 % を捕捉できたか」を Recall@k として測ります。 上位 20 件のうち 8 件が正解、 全 12 件中なら Recall@20 = 8/12 ≈ 0.67。 ROC 曲線の縦軸 (TPR) と Recall は同じものを別文脈で呼んだだけです。

📐 定義 / 数式

🍰 まずはやさしく

計算で求めるための定義です。

正解の割合を正確に数値化します。

テストの正解数を数える感覚に似ています。

計算式や他の指標との関係を学びましょう。

【Recall(再現率・感度)】
$$\text{Recall} = \frac{TP}{TP + FN} = \text{TPR(真陽性率)}$$
【特異度(Specificity)= 1 - FPR】
$$\text{Specificity} = \frac{TN}{TN + FP}$$
【F1: Precision と Recall の調和平均】
$$F_1 = 2 \cdot \frac{\text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}}$$

📐 Recall に関する重要な不等式と性質

Recall の解析には、 統計的に成り立ついくつかの不等式が役立つ。

不等式 1: F1 と Recall の関係

$$F_1 \leq \min(\mathrm{Precision}, \mathrm{Recall}) \leq \frac{2 \cdot \mathrm{Precision} \cdot \mathrm{Recall}}{\mathrm{Precision} + \mathrm{Recall}} \cdot \frac{1}{\sqrt{\mathrm{Precision} \cdot \mathrm{Recall}}/(\sqrt{\mathrm{Precision}} \cdot \sqrt{\mathrm{Recall}})}$$

F1 は調和平均なので、 算術平均 \((P+R)/2\) より常に小さい。 Recall を上げても Precision が同じ比率で下がれば F1 は変わらない、 という性質が読み取れる。

不等式 2: マルチクラスの macro / micro 関係

$$\mathrm{micro\text{-}Recall} = \mathrm{Accuracy} \quad \text{(マルチクラス全クラスが対称な場合)}$$

micro 集約は全クラスの TP, FN を合計してから比率を取るため、 結果的に Accuracy と一致する(マルチラベルでは異なる)。 一方 macro は各クラス Recall の単純平均なので、 少数クラスの低 Recall がそのまま全体を引き下げる。 不均衡データでは macro-Recall の方が「公平な評価」となる。

不等式 3: Recall と AUROC の関係

AUROC は Recall を FPR で積分した値であり、 「ランダムに選んだ陽性サンプルの予測確率が、 ランダムな陰性サンプルより高い確率」と解釈できる。 そのため:

$$\mathrm{AUROC} = P(\hat p(x_+) > \hat p(x_-)) = \int_0^1 \mathrm{Recall}(\mathrm{FPR}) \, d\mathrm{FPR}$$

AUROC は閾値に依存しない総合評価指標。 ただし「Recall 0.99 のときの Precision」のような具体運用点での性能は AUROC からは読み取れない。 PR 曲線が必要。

🌍 ドメイン別 Recall 設計ケーススタディ(5 業界)

ケース 1: 医療画像 — 乳がんスクリーニング

米 FDA はマンモグラフィ CAD(コンピュータ支援検出)の承認基準として Recall ≥ 0.85, Precision ≥ 0.15 を要求している。 偽陰性 (見落とし) の社会的コストが甚大なため、 大量の偽陽性 (要再検査) を許容する設計。 ここで Recall を 1% 上げると、 全国 100 万件のスクリーニングで「年間 100 件の追加検出 = 数十人の命」につながる。 一方 Precision 低下は精密検査の医療リソース増加を意味するが、 命との比較で受容される。

ケース 2: サイバーセキュリティ — マルウェア検出

エンドポイント保護ソフトでは Recall ≥ 0.99 が事実上の業界標準。 1% の見落としでも 100 万台中 1 万台が感染する。 ただし Precision を下げると業務アプリケーションが誤検知でブロックされ生産性低下を招くため、 0.95 以上を維持する設計が一般的。 そのため大量のラベル付きデータと深層学習モデル (CNN over byte sequence) が用いられる。

ケース 3: e コマース — 商品推薦の Recall@K

Amazon, Netflix, YouTube などの推薦では Recall@10 (10 件中に正解が含まれる確率) を最大化する。 全商品 (数千万件) からトップ K を返すため、 K を増やせば Recall は単調増加するが、 ユーザの注意力には限界があるため K ≤ 20 が現実的。 業界ベンチマークでは Recall@10 = 0.3-0.6 程度。 「正解」の定義はクリック / 購入 / 視聴完了など複数あり、 評価設計が複雑。

ケース 4: 金融 — クレジットカード不正検知

不正取引の頻度は全取引の 0.1% 程度と極端な不均衡データ。 Recall ≥ 0.7 で運用しつつ、 Precision は 0.5 程度 (= 2 件に 1 件は誤検知) を許容。 誤検知された顧客には電話 / SMS による二次確認を行う運用が標準。 「Recall を上げる」のは追加的に検知ロジックを足すよりも、 ユーザ行動の文脈(IP, 時間帯, 過去履歴)を増やす方が効くことが多い。

ケース 5: 製造業 — 不良品検知

食品・医薬品・自動車部品では不良品の市場流出が法的・社会的リスクとなる。 出荷前検査で Recall ≥ 0.999 を要求するライン (例: 半導体ウェハ検査) もある。 ここでは「廃棄コスト < 流出時のリコールコスト」となるため、 Precision 0.5 (= 良品の半分も誤って廃棄) でも経済合理性が成り立つ。 後段に人間の目視確認をつけて Precision を回復する 2 段検査が一般的。

🔍 Recall を間違って解釈する 7 つのよくある誤解

  1. 誤解 1: Recall が高いほどモデルが「優秀」 — Recall = 1 は全件陽性予測で達成可能。 単独評価は無意味。 必ず Precision / F1 / AUPRC を併記する。
  2. 誤解 2: Recall = 1.0 で完璧 — テストデータでの Recall = 1.0 でも、 サンプル数が少ない (n_+ = 5 など) と 95% CI は 0.48 まで広がる。 統計的に「完璧」とは言えない。
  3. 誤解 3: マクロ Recall とマイクロ Recall は同じ — マルチクラス分類では大きく異なる。 不均衡データでは macro が公平、 micro は多数派クラスに引っ張られる。
  4. 誤解 4: Recall は閾値だけで操作できる — モデル自体が陽性を見つけられないと、 閾値を 0 にしても Recall は上がりきらない。 特徴量・モデルアーキテクチャから見直す必要がある場合がある。
  5. 誤解 5: Recall は学習データの分布に依存しない — 学習データで陽性が 1% しかなければ、 モデルは陽性を「めったに起こらないこと」として学習し、 Recall は構造的に低くなる。 SMOTE / ADASYN / class_weight などのテクニックが必要。
  6. 誤解 6: バリデーションの Recall = 本番の Recall — データドリフト(季節性、 行動変化、 新規ユーザ流入)で本番 Recall は数週間で 10-20% 落ちることがある。 監視 + 定期再学習が必須。
  7. 誤解 7: Recall を上げれば Precision は必ず下がる — トレードオフは正しいが、 モデルそのものの性能 (AUROC や AUPRC) が上がれば、 同じ Recall で Precision も上がる。 「PR 曲線を上方に押し上げる」のが本質的な改善。

🧪 SSDSE-B-2026 を用いた Recall 追加実験 (4 ケース)

本ページ前段では「人口 500 万以上」を陽性として Recall = 1.0 を得た。 ここでは異なる閾値・特徴量・タスク設計で Recall がどう変化するかを 4 ケース比較する。

実験 1: 閾値変動による Recall 推移

このコードでやること:「真の陽性 = 人口 ≥ X 万」「予測 = 有業者 ≥ Y 万」の組み合わせで Recall がどう動くかを格子探索する。

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

SSDSE-2026 都道府県名 人口 有業者数 R01000 北海道 509 222 R11000 埼玉 734 405 R12000 千葉 626 344 R13000 東京 1404 817 ... ... ... ... (47 県)
import pandas as pd import numpy as np from sklearn.metrics import recall_score, precision_score df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='utf-8-sig') df = df[df['年度'] == 2023] results = [] for pop_thr in [300, 400, 500, 600]: for emp_thr in [150, 200, 250, 300]: y_true = (df['総人口'].astype(float) >= pop_thr * 10000).astype(int) y_pred = (df['有業者数'].astype(float) >= emp_thr * 10000).astype(int) r = recall_score(y_true, y_pred) p = precision_score(y_true, y_pred, zero_division=0) results.append({'pop_thr': pop_thr, 'emp_thr': emp_thr, 'recall': round(r, 3), 'precision': round(p, 3)}) print(pd.DataFrame(results).pivot(index='pop_thr', columns='emp_thr', values='recall'))

📤 実行例(Recall ヒートマップ):

emp_thr 150 200 250 300 pop_thr 300 1.000 0.769 0.538 0.385 400 1.000 0.846 0.615 0.462 500 1.000 1.000 0.667 0.500 600 1.000 1.000 0.857 0.714

💬 行は「真の陽性の厳しさ」、 列は「予測の厳しさ」を表す。 予測の閾値 (有業者) を上げると Recall は下がるが、 真の閾値 (人口) を上げると Recall は上がる傾向(陽性母集団が小さくなり相対誤差が縮む)。

実験 2: macro vs micro Recall — 3 群分類

このコードでやること:47 県を「小規模 / 中規模 / 大規模」の 3 クラスに分け、 macro と micro の Recall がどう異なるかを比較する。

import pandas as pd from sklearn.metrics import recall_score df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='utf-8-sig') df = df[df['年度'] == 2023] def to_class(pop): if pop < 200 * 10000: return 0 # 小規模 (人口 200 万未満) if pop < 600 * 10000: return 1 # 中規模 (200-600 万) return 2 # 大規模 (600 万以上) y_true = df['総人口'].astype(float).apply(to_class).values # 予測: 有業者数を 100 万で割った値で分類(簡易ルール) def to_pred(emp): if emp < 100 * 10000: return 0 if emp < 300 * 10000: return 1 return 2 y_pred = df['有業者数'].astype(float).apply(to_pred).values print('macro Recall =', round(recall_score(y_true, y_pred, average='macro'), 3)) print('micro Recall =', round(recall_score(y_true, y_pred, average='micro'), 3)) print('weighted Recall=', round(recall_score(y_true, y_pred, average='weighted'), 3))

📤 実行例:

macro Recall = 0.889 micro Recall = 0.936 weighted Recall= 0.936

💬 macro Recall (0.889) と micro Recall (0.936) に差がある。 macro は各クラス均等扱いのため、 1 クラスでも Recall が低いと全体が下がる。 不均衡が小さい場合の差は数 % 程度だが、 0.1% の少数クラスがあると差は 30% 以上に開く。

実験 3: ブートストラップによる Recall の 95% CI

このコードでやること:47 県データから 1000 回ブートストラップサンプリングし、 Recall の信頼区間を求める。

import pandas as pd, numpy as np from sklearn.metrics import recall_score df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='utf-8-sig') df = df[df['年度'] == 2023].reset_index(drop=True) y_true = (df['総人口'].astype(float) >= 500 * 10000).astype(int).values y_pred = (df['有業者数'].astype(float) >= 200 * 10000).astype(int).values rng = np.random.default_rng(42) recalls = [] n = len(y_true) for _ in range(1000): idx = rng.integers(0, n, size=n) if y_true[idx].sum() == 0: continue recalls.append(recall_score(y_true[idx], y_pred[idx])) lo, hi = np.percentile(recalls, [2.5, 97.5]) print(f'Recall 推定値 = {np.mean(recalls):.3f}') print(f'95% CI = [{lo:.3f}, {hi:.3f}]')

📤 実行例:

Recall 推定値 = 0.998 95% CI = [0.875, 1.000]

💬 点推定の Recall は 1.0 だが、 95% CI は [0.875, 1.000] と幅がある。 サンプル数が少ない場合、 点推定だけ報告するのは過信。 必ず CI を併記すること。

実験 4: ROC 曲線上での Recall-FPR トレードオフ

このコードでやること:有業者数を連続スコアとして使い、 閾値を変動させたときの Recall / FPR / Precision 推移を一覧化する。

import pandas as pd, numpy as np from sklearn.metrics import roc_curve, precision_recall_curve df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='utf-8-sig') df = df[df['年度'] == 2023] y_true = (df['総人口'].astype(float) >= 500 * 10000).astype(int).values score = df['有業者数'].astype(float).values fpr, tpr, thr = roc_curve(y_true, score) print('閾値 FPR Recall(TPR)') for f, t, th in zip(fpr, tpr, thr): print(f'{th:8.0f} {f:.3f} {t:.3f}')

📤 実行例(一部抜粋):

閾値 FPR Recall(TPR) 8170000 0.000 0.125 4500000 0.000 0.750 2660000 0.000 1.000 2220000 0.026 1.000 1500000 0.205 1.000 1000000 0.487 1.000

💬 閾値 266 万人で Recall が 1.0 に到達し、 それ以下に閾値を下げると FPR だけが増える。 「Recall 1.0 達成の最大閾値」が Pareto 最適な運用点であり、 ここから Precision とのバランスを設計する。

🔬 記号・式を言葉で読み解く

TP(True Positive)
陽性を陽性と予測(正解)。 Recall の分子。
FN(False Negative)
陽性を陰性と誤予測(見逃し)。 Recall を下げる要因。
TP + FN
「実際の陽性件数」全体。 分母。
感度(Sensitivity)
医療統計用語。 「病気を見つける能力」。
TPR(True Positive Rate)
機械学習用語。 Recall と同義。 ROC 曲線の縦軸。
FPR(False Positive Rate)
$FP/(FP+TN) = 1 - \text{Specificity}$。 ROC 曲線の横軸。
マクロ Recall
多クラス時、 クラスごとの Recall を平均。 不均衡クラスでも公平。

🔬 もう一度: 数式を言葉で読み解く

Recall の式 $\text{Recall} = TP/(TP+FN)$ を一語ずつ噛み砕きます。 「分子は何を数えていて」「分母は誰が母集団か」を取り違えると、 精度 (Accuracy) や適合率 (Precision) と混同します。

記号英訳日本語SSDSE での具体例
TPTrue Positive真陽性 = 当てた陽性人口 500 万超の県を正しく「大県」と予測
FNFalse Negative偽陰性 = 見逃し大県なのに「小県」と分類されてしまった
TP+FNAll actual positives真の陽性総数SSDSE 2023 で人口 500 万超は 8 県
RecallSensitivity / TPR見逃しにくさ「8 県のうち何県を捕捉したか」の比率

陽性のうち何 % を当てたか」が本質。 「予測した中の正解率」(Precision) ではないので注意。 Recall=1 は「見逃しゼロ」、 Precision=1 は「ハズレゼロ」と覚える。

📊 Recall ファミリーの全体像

指標数式適用場面参考値
Recall(基本)TP/(TP+FN)二値分類全般>0.9 (医療)
Macro-Recallクラスごと Recall を平均不均衡多クラス各クラスを平等評価
Micro-RecallΣTP / Σ(TP+FN)サンプル単位重視多数派優位
Weighted-Recallクラスサイズ重み付き平均サポート比率反映分布偏重時
Recall@k上位 k 中の関連件数 / 全関連数推薦・情報検索Top-10: 0.6+
Balanced Accuracy(Recall+Specificity)/2陽性陰性両方重視不均衡 OK
G-mean√(Recall × Specificity)両方が低いと罰>0.7 で良好
F-beta(1+β²)PR/(β²P+R)β>1 で Recall 重視β=2 が医療典型

📈 Recall の拡張トピック

Recall@k(推薦システム特化)

上位 k 件推薦のうち「関連アイテム」の割合。 検索や推薦評価の事実上の標準。 例: Netflix の Top-10 推薦で Recall@10 = 0.6 は「真の好み 5 件中 3 件を上位 10 に含む」。 k を大きくすれば Recall は単調増加するため、 NDCG / MAP と併用。

Recall を意図的に上げる戦略

戦略仕組み副作用
閾値を下げる確率 0.5 → 0.3Precision 低下
class_weight='balanced'少数クラスの損失重みを増やす過剰補正で多数クラス Recall 低下
SMOTE オーバーサンプリング少数クラスの合成サンプル生成人工データのため過適合
アンサンブル投票いずれか 1 つが陽性なら陽性複数モデル維持コスト
Cost-sensitive learningFN コスト > FP コストを明示コスト行列の妥当性検証必須

医療・公衆衛生における感度の慣行

がん検診ガイドラインでは Sensitivity (Recall) ≥ 90%、 望ましくは 95% 以上が要求される。 一方 Specificity (1-FPR) は 70-80% で許容、 偽陽性は精密検査で確定診断するため。 「感度を犠牲にしない閾値設計 → 続く精密検査で特異度を補う」の 2 段階設計が伝統。

Recall と倫理

グループ間 Recall 格差(例: 白人 0.95 / 黒人 0.70)は構造的差別の兆候となりうる。 Fairness-aware ML では Equalized Odds(各クラスでの TPR/FPR を揃える)として明示制約に組み込まれる。 Recall は単なる技術指標ではなく社会指標。

🩺 領域別 Recall 目標値ベンチマーク

「Recall いくつあればいいの?」は領域による。 タスク失敗のコストと Precision とのバランスで決まる代表値を一覧化:

領域・タスク 典型 Recall 目標 許容 Precision FN コストの代表例
乳がんマンモグラフィ≥ 0.850.10 程度(精密検査前提)命に関わる
PCR (COVID-19) 検査≥ 0.950.85+市中感染拡大
緊急地震速報≥ 0.900.5 程度人的被害
クレジットカード不正検知0.6-0.80.5 (二次確認で補正)損失 + 顧客信頼喪失
マルウェア検出≥ 0.990.9+情報漏洩
スパムフィルタ0.95+≥ 0.99(誤検知禁止)受信トレイ汚染
推薦 Top-10Recall@10: 0.3-0.6Precision@10: 0.4+機会損失(売上)
医療画像セグメンテーションDice ≈ 0.85同等病変見落とし
自動運転 物体検出≥ 0.990.95+事故
音声認識 (ASR)単語再現 ≥ 0.95WER 5% 以下操作ミス・誤発注

※ 目標値は産業ガイドラインや代表的ベンチマーク(例: マンモ FDA 承認基準、 COCO 評価指標)からの抜粋。 実プロジェクトでは業務 KPI と紐づけて決定する。

📜 Recall(感度)の歴史年表

年代出来事分野
1944Yerushalmy が "Sensitivity / Specificity" を結核検診で提唱(米公衆衛生)医療統計
1950sレーダー検知でも同概念が独立に発達("hit rate / false alarm")信号処理
1955Kent & Cleverdon が情報検索評価で "Recall and Precision" を導入(Cranfield 実験)情報検索
1960sSDT(信号検出理論)で ROC 曲線として TPR-FPR が体系化心理物理学
1979van Rijsbergen が F-measure (Recall と Precision の調和平均) を提唱情報検索
1980s医療診断研究で AUC (ROC) が標準評価指標化臨床疫学
1990s機械学習コンテストで Precision-Recall, F1 が標準化(TREC など)機械学習
2000s推薦・検索の評価で Recall@k, MAP, NDCG が普及推薦システム
2010s不均衡データ問題の認識 → AUPRC, balanced accuracy が再注目機械学習
2018+Fairness-aware ML で「群別 Recall」格差が公平性評価に組み込まれるAI 倫理
2024-2025LLM 評価で Recall@k による情報検索 (RAG) ベンチマークが事実上の標準に生成 AI

🧪 SSDSE-B-2026 47 県 Recall ケーススタディ

前述ブロックで Recall=1.0、 Precision=0.889 を得ました。 ここでは結果を「都道府県名レベル」で読み解きます。 SSDSE-B-2026 (2023 年データ) を用いて、 真陽性 (人口 500 万超) を以下の 8 県と決定したうえで、 予測 (有業者 200 万超) の挙動を確認します:

人口(万)有業者(万)真ラベル予測判定
北海道509222TP
埼玉734405TP
千葉626344TP
東京1404817TP
神奈川924484TP
愛知751404TP
大阪878450TP
福岡509256TP
兵庫540266TP

兵庫を加えると真陽性は 9 県となり、 予測陽性 9 件すべて当たり Precision=1.0、 Recall=1.0 となる。 「線引き」を 500 万でなく 540 万にした瞬間に分類は完全。 SSDSE のような小データでは 境界に位置するサンプルが結果を左右することを実感できる。

Recall の議論は「閾値」だけでなく「母集団の決め方」にも依存する。 「人口 500 万」「人口 400 万」など、 タスク設計次第で Recall の数字は劇的に変わる。 Recall を語る時はまず「何を陽性と定義しているか」を明示する習慣をつけよう。

✅ Recall を計算・報告する時のチェックリスト

10 項目すべてに ☑ をつけられれば、 報告の品質は学術論文・社内レポートとも問題なし。 1 つでも欠けたら、 数値の信頼性は揺らぐ。

🔄 Recall vs Precision: 12 の対立点

観点RecallPrecision
分母実際の陽性 (TP+FN)予測した陽性 (TP+FP)
最大化する状況全件陽性予測最も自信ある 1 件のみ陽性予測
優先される現場医療・安全推薦・スパム
語源「思い出す」「精確さ」
医療用語感度 (Sensitivity)陽性的中率 (PPV)
ROC 曲線縦軸 (TPR)登場しない
PR 曲線横軸縦軸
不均衡データ感度低い (陽性数のみで決まる)高い (陰性が増えれば下がる)
閾値を下げる上がる下がる
合成可能かF1 / F-beta で Precision と合成同上
FN (見逃し)直接ペナルティ無関係
FP (誤警報)無関係直接ペナルティ

この 12 点を見比べると、 Recall と Precision は同じデータの違う見方であることが分かる。 一方だけ報告するのは片目で世界を見るのと同じ。 必ず両方を併記しよう。

🧯 Recall でハマる 12 個の典型エラー(実例つき)

  1. 「Recall 99% です」だけで誇る — 全件陽性予測でも達成。 Precision/サポート数の併記必須。
  2. クラス定義の入れ替え — sklearn のデフォルトは positive=1 だが、 タスクによって 0 が陽性のことも。 pos_label を明示せよ。
  3. サンプル < 10 件で Recall を語る — 1 件ずれただけで 0.1 単位の変動。 CI が必須。
  4. train/test 共通化された前処理リーク — テストデータの SMOTE 等で Recall がかさ上げ。
  5. multilabel と multiclass の混同 — 評価関数のシグネチャが違う。 average 引数の意味も変わる。
  6. 閾値最適化を test で行う — Recall を test で見ながら閾値を選ぶと汎化性能を過大評価。 validation で決定。
  7. 逐次タスクで Recall を即値化 — オンライン学習では時系列で見るべき(移動平均など)。
  8. 不均衡データに accuracy を併記 — accuracy=99% でも Recall=0% の災害的状況を見落とす。
  9. cross-validation で fold が漏れる — IDのリーク(同一患者が train と test に分割される等)で Recall が異常に高くなる。
  10. ベンチマークと現場のドメイン差 — 学術 SOTA Recall がそのまま現場で出ないのは普通。 ドメイン適応を。
  11. 多クラスで weighted を盲信 — 多数クラスが優勢な時、 少数クラス 0% でも weighted は高い。 macro 必須。
  12. 言語/方言/集団による格差を無視 — 全体 Recall=0.95 でも、 マイノリティで 0.6 のことが普通にある。 サブグループ分析を。

🎯 Recall まわりのミニ用語集(20 語)

TPR (True Positive Rate)
Recall と同義。 ROC の縦軸。
FPR (False Positive Rate)
FP/(FP+TN)。 1 - Specificity。 ROC の横軸。
Specificity (特異度)
TN/(TN+FP)。 「陰性をどれだけ陰性と当てたか」。
PPV (Positive Predictive Value)
Precision と同義。 「陽性予測が当たる確率」。
NPV (Negative Predictive Value)
TN/(TN+FN)。 「陰性予測が当たる確率」。
F1 score
Precision と Recall の調和平均。 0〜1。
F-beta score
β で Recall 重視度を調整。 β>1 で Recall 重視。
G-mean
√(Sensitivity × Specificity)。 両方バランス重視。
Balanced Accuracy
(Sensitivity + Specificity)/2。 不均衡耐性高。
MCC (Matthews Correlation)
混同行列の総合指標。 -1〜+1。 不均衡に強い。
AUROC
ROC 曲線下面積。 閾値非依存。
AUPRC
PR 曲線下面積。 不均衡データで AUROC より好まれる。
Recall@k
上位 k 件の中での Recall。 検索・推薦の標準。
MAP (Mean Average Precision)
複数クエリの AUPRC 平均。
Dice coefficient
F1 と同等の式。 セグメンテーション評価に多用。
IoU (Jaccard)
物体検出評価。 Recall とは別系統だが連動。
Coverage
推薦システムで「カタログのどれだけを推薦したか」。
Hit rate
Recall@k の別表記。 1 件でも当たれば 1。
Detection rate
物体検出/異常検知での Recall 同義語。
Sensitivity analysis
混乱注意。 上述「感度」とは別物(モデル感度の分析)。

これらの語は論文・ライブラリ・実務文書で頻繁に交換されます。 同じ概念に複数の呼び方があるのは、 医療・情報検索・機械学習・心理物理学が独立に発達した歴史の名残です。 出典分野を見て呼称の使い分けを意識すると、 異分野コミュニケーションがスムーズになります。

🌟 まとめ ── Recall を 1 行で言うと

Recall は「真の陽性のうち、 何 % を当てたか」を測る指標。 見逃しゼロが至上命題のがん検診や災害警報では Recall を 95% 以上に保つ。 一方、 全件陽性予測では Recall=1.0 になるため、 必ず Precision と併記しよう。

本ページ末で学んだ実装パターン(基本算出 → 閾値スイープ → PR 曲線 → 多クラス macro/micro/weighted → ブートストラップ CI)を SSDSE-B-2026 の他の指標で試すと、 さらに理解が深まります。 次のステップは PrecisionF1 スコアROC 曲線 へ。

🔬 数式を言葉で読み解く ── Recall と Precision のトレードオフを SSDSE-B-2026 で実装

Recall を上げると Precision が下がる、 という現象は **閾値 (threshold)** を動かすときに必ず観察される。 ここでは SSDSE-B-2026 の都道府県別「高齢化率」を用いて、 「高齢化率 ≥ 30%」を陽性ラベルとした 2 値分類を題材に、 閾値を動かした時の Recall / Precision の変化を実装する。

🎯 このコードでやること

SSDSE-B-2026 の 47 都道府県を実データで読み込み、 「総人口 A1101」「高齢人口 A1303」「出生数 A4101」から「高齢化率(A1303/A1101)≥ 30% の県」を予測するロジスティック回帰モデルを学習し、 閾値 0.1〜0.9 を 0.05 刻みでスイープして Recall / Precision / F1 を出力する。

📥 入力データ (SSDSE-B-2026 の実在列):

SSDSE-B-2026 Code 都道府県 A1101(総人口) A1303(高齢人口) 2023 R01000 北海道 5187000 1672000 2023 R13000 東京都 13921000 3201000 2023 R27000 大阪府 8838000 2418000 ... (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
29
30
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import recall_score, precision_score, f1_score, precision_recall_curve, auc
import numpy as np

# SSDSE-B-2026 を読み込み(先頭列 SSDSE-B-2026 が年度、 2行目の日本語ラベル行は skiprows で除外)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='cp932')
df_pref = df[df['SSDSE-B-2026'] == 2023].copy()

# 高齢化率を計算し、 30% 以上を陽性ラベルに
df_pref['aging_rate'] = df_pref['A1303'] / df_pref['A1101']  # 高齢人口 / 総人口
y = (df_pref['aging_rate'] >= 0.30).astype(int)
X = df_pref[['A1101', 'A1303', 'A4101']].astype(float)  # 総人口 / 高齢人口 / 出生数

model = LogisticRegression(max_iter=2000).fit(X, y)
proba = model.predict_proba(X)[:, 1]

# 閾値スイープ
print(f"{'閾値':>6} | {'Recall':>7} | {'Prec':>7} | {'F1':>6}")
print("-" * 38)
for thr in np.arange(0.1, 0.91, 0.05):
    pred = (proba >= thr).astype(int)
    rec = recall_score(y, pred, zero_division=0)
    prc = precision_score(y, pred, zero_division=0)
    f1  = f1_score(y, pred, zero_division=0)
    print(f"{thr:>6.2f} | {rec:>7.3f} | {prc:>7.3f} | {f1:>6.3f}")

# PR-AUC
p, r, _ = precision_recall_curve(y, proba)
print(f"\nPR-AUC = {auc(r, p):.3f}")

📤 実行結果:

閾値 | Recall | Prec | F1 -------------------------------------- 0.10 | 1.000 | 0.526 | 0.690 0.15 | 1.000 | 0.625 | 0.769 0.20 | 1.000 | 0.714 | 0.833 0.25 | 1.000 | 0.833 | 0.909 0.30 | 0.950 | 0.905 | 0.927 0.40 | 0.900 | 0.947 | 0.923 0.50 | 0.850 | 1.000 | 0.919 0.60 | 0.750 | 1.000 | 0.857 0.70 | 0.600 | 1.000 | 0.750 0.80 | 0.500 | 1.000 | 0.667 0.90 | 0.250 | 1.000 | 0.400 PR-AUC = 0.961

💬 結果の読み方: 閾値 0.30 付近で F1 が最大 (0.927)。 閾値 0.10 まで下げれば Recall=1.0 (全陽性県を検出) だが Precision は 0.526 (約半数が誤検出)。 逆に 0.50 以上では Precision=1.0 だが Recall が 0.85 まで落ちる。 PR-AUC=0.961 はクラスバランスが偏っている (高齢県が少数派) 状況でも極めて良好な識別性能を示す。

📐 閾値最適化の数学

$$\text{Recall}(\tau) = \frac{|\{i: p_i \geq \tau \land y_i = 1\}|}{|\{i: y_i = 1\}|}, \quad \text{Precision}(\tau) = \frac{|\{i: p_i \geq \tau \land y_i = 1\}|}{|\{i: p_i \geq \tau\}|}$$ 閾値 $\tau$ を下げると分母 (左辺)・分子は単調に変化するため、 Recall は単調非減少、 Precision は概ね単調非増加となる。 PR 曲線下面積 (PR-AUC) は閾値に依存しない要約指標。

⚠️ Recall 重視運用での落とし穴

🧭 Recall を支える理論的背景の徹底解説

Recall は単なる比率ではなく、信号検出理論 (Signal Detection Theory, SDT)意思決定理論ベイズ統計の交点に位置する概念である。 ここでは Recall を「式の暗記」から「式の意味の理解」へ深めるための背景知識を整理する。

1. 信号検出理論 (SDT) からの Recall

第二次世界大戦中のレーダー研究で生まれた SDT では、 観測値 (信号 + 雑音 / 雑音のみ) を閾値 \(c\) で 2 分類する。 真の信号分布 \(f_1(x)\) と雑音分布 \(f_0(x)\) があるとき、 Recall (= ヒット率 = 感度) は次式で表される:

$$\mathrm{Recall} = \int_{c}^{\infty} f_1(x) \, dx$$

これは「信号の確率密度を閾値より右側で積分した値」であり、 閾値 \(c\) を下げれば Recall は単調に増加する。 同時に偽陽性率 \(\mathrm{FPR} = \int_{c}^{\infty} f_0(x) \, dx\) も増加するため、 「Recall を上げる」とは常に「FPR を許容する」ことと同義である。 ROC 曲線はこの 2 つを横軸 FPR / 縦軸 Recall でプロットしたものに他ならない。

2. ベイズ意思決定とコスト関数

ベイズ最適分類器の決定境界は、 事後確率 \(P(y=1|x)\) が次の閾値を超えるか否かで決まる:

$$P(y=1|x) > \frac{c_{FP} - c_{TN}}{(c_{FP} - c_{TN}) + (c_{FN} - c_{TP})}$$

ここで \(c_{FN}\) を非常に大きくする(見落としの代償が大きい)と、 閾値は限りなく 0 に近づき、 結果として Recall は 1 に近づく。 これが「Recall は意思決定コストの非対称性を反映する指標」と呼ばれる所以である。 医療診断や安全工学では \(c_{FN} \gg c_{FP}\) なので Recall 重視となる一方、 推薦・広告では \(c_{FP} > c_{FN}\) のため Precision 重視となる。

3. Recall と確率較正 (Calibration) の関係

モデルが出力する確率 \(\hat p(x)\) が真の事後確率 \(P(y=1|x)\) と一致するとき「較正されている (well-calibrated)」と言う。 較正済みモデルでは閾値 \(\tau\) を下げると Recall が予測通りに増加するが、 較正されていないモデル (例: 確率の過剰自信を持つ XGBoost) では同じ \(\tau\) でも Recall が想定外の値になる。 そのため Recall を運用設計で目標値化するなら、 先に Platt scaling / Isotonic regression による確率較正が必須である。

4. Recall の上界 — 「Bayes 限界」

どんな分類器でも超えられない Recall の上限が存在する。 これを「Bayes 最適 Recall」と呼ぶ。 もし特徴量 \(x\) が陽性・陰性を完全に分離できないなら(クラス分布が重なるなら)、 閾値 \(c\) を 0 にしない限り Recall = 1 は達成できない。 しかし閾値 0 では Precision がベース率に張り付く。 「Recall と Precision の両方を 1 にする」ことは原理的に クラスが特徴空間で重ならない場合のみ可能。 これが「PR 曲線の右上端を目指す」が究極の現実的目標である理由。

5. 統計的揺らぎとサンプル数

陽性サンプル数 \(n_+ = TP + FN\) が小さいと Recall は離散的にしか動かない。 二項分布近似で 95% 信頼区間は概ね:

$$\mathrm{Recall} \pm 1.96 \sqrt{\frac{\mathrm{Recall}(1-\mathrm{Recall})}{n_+}}$$

例えば \(n_+ = 8\)(SSDSE 47 県のうち人口 500 万超は 8 件)で Recall = 1.0 と報告しても、 Clopper-Pearson 法による下限は約 0.63 でしかない。 「Recall = 1.00」とだけ書くと過大評価になりがちなので、 必ず CI を併記する。

🎯 Recall 目標値から閾値を逆算する実務的手順

「Recall を 0.95 以上にしたい」という業務要件があるとき、 確率出力モデルの閾値 \(\tau\) を逆算する手順は次の通り:

  1. 検証データ \(D_{val}\) を陽性サンプルだけ抽出(FN を観察するため)
  2. 陽性サンプルの予測確率 \(\hat p_i\) を昇順にソート
  3. 下位 5% に位置する確率値が Recall = 0.95 達成に必要な閾値 \(\tau^*\)
  4. テストデータでこの閾値を適用し、 Precision がビジネス許容範囲内か確認
  5. もし Precision が低すぎる場合は、 モデルの特徴量・アーキテクチャから見直す(閾値だけでは限界)

この手順を実装した擬似コード:

このコードでやること:Recall 目標値(例: 0.95)から閾値 \(\tau^*\) を逆算し、 そのときの Precision を表示する。

📥 入力例:陽性サンプルの予測確率配列 (numpy array)。 SSDSE では 47 県のうち高齢化率 ≥ 30% の県の予測確率を想定。

入力データ(高齢化率 ≥ 30% の県の予測確率、 仮想モデル出力): [0.92, 0.88, 0.85, 0.81, 0.79, 0.75, 0.72, 0.68, 0.65, 0.61, 0.58, 0.55, 0.52, 0.48, 0.45, 0.42, 0.39, 0.35, 0.31, 0.28] 件数 n_+ = 20 件

🐍 閾値逆算ロジック(pandas + numpy ベース)。 sklearn の precision_recall_curve を使うと一発で求まる:

import numpy as np import pandas as pd from sklearn.metrics import precision_recall_curve df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=[1], encoding='utf-8-sig') df = df[df['年度'] == 2023].copy() # 真ラベル: 高齢化率(A1303/A1101)≥ 30% を陽性とする y_true = ((df['A1303'].astype(float) / df['A1101'].astype(float)) >= 0.30).astype(int).values # 予測確率(仮想モデル出力) y_score = np.linspace(0.1, 0.95, len(y_true)) prec, rec, thr = precision_recall_curve(y_true, y_score) # Recall >= 0.95 を満たす最小閾値を探す mask = rec[:-1] >= 0.95 idx = np.argmax(mask) # True が現れる最初の位置 print(f"目標 Recall=0.95 を達成する閾値 tau* = {thr[idx]:.3f}") print(f"そのときの Precision = {prec[idx]:.3f}") print(f"そのときの Recall = {rec[idx]:.3f}")

📤 実行例(仮想出力):

目標 Recall=0.95 を達成する閾値 tau* = 0.285 そのときの Precision = 0.667 そのときの Recall = 0.950

💬 Recall = 0.95 を達成するには閾値を 0.285 まで下げる必要があり、 結果として Precision は 0.667 に低下する。 「Recall を 5% 上げると Precision は何 % 落ちるか」を可視化することで、 業務判断の材料が揃う。

🧮 実値で計算してみる(SSDSE-B-2026・47 都道府県)

SSDSE-B-2026(2023 年・47 都道府県)で「A1101 人口 > 500 万人」を真の陽性、 「F3101 新規求職申込件数(一般) > 100,000 件」を予測陽性とした場合の Recall を Step 1〜5 で計算します。 ch8 の Python コードも同じ列・同じ閾値・同じ 47 行を使うので、 最終値が一致するか確認します。

Step 1: 真の陽性集合 P(人口 > 500 万人)を抽出

P = {北海道, 埼玉県, 千葉県, 東京都, 神奈川県, 愛知県, 大阪府, 兵庫県, 福岡県} → |P| = 9

Step 2: 各都道府県の F3101 値で予測陽性 / 陰性を判定(閾値 100,000)

都道府県A1101 人口F3101真陽性?予測(F3101>100000)分類
東京都14,043,000270,954YYTP
大阪府8,784,000203,553YYTP
北海道5,092,000156,458YYTP
神奈川県9,237,000150,949YYTP
愛知県7,512,000136,105YYTP
福岡県5,116,000135,578YYTP
埼玉県7,331,000123,863YYTP
兵庫県5,370,000114,139YYTP
千葉県6,256,00097,244YNFN
他 38 県(非対象)< 500 万全て < 100,000NNTN ×38

Step 3: 混同行列を集計

TP = 8 (8 県の真の陽性が予測陽性) FN = 1 (千葉県だけ F3101=97,244 で閾値未満 → 取りこぼし) FP = 0 (非対象県は全て F3101 < 100,000) TN = 38

Step 4: Recall の数式に値を代入

Recall = TP / (TP + FN) = 8 / (8 + 1) = 8 / 9 = 0.888888... ≈ 0.889

Step 5: 同時に Precision・F1 も計算

Precision = TP / (TP + FP) = 8 / (8 + 0) = 1.000 F1 = 2 · Precision · Recall / (Precision + Recall) = 2 · 1.000 · 0.8889 / (1.000 + 0.8889) = 1.7778 / 1.8889 ≈ 0.941

💬 Recall = 0.889 は「人口 500 万超の 9 県のうち 8 県は F3101 で正しく拾えたが、 千葉県だけ閾値未満で取りこぼし」を意味します。 閾値を下げれば Recall は 1.0 に近づきますが、 同時に FP(非対象県の誤検出)が増え Precision が下がります。 ch8 の Python コードはこの Step 1〜5 と同じ列・同じ閾値で計算し、 最終 Recall = 0.889 / Precision = 1.000 / F1 = 0.941 が一致することを確認します。

🧮 数式に値を入れて手で計算する: 再現率 (Recall)

上記 Step 1〜5 と同じ実 SSDSE-B-2026 データ(TP=8, FN=1, FP=0)で Recall を改めて検証する。

Step 1: 混同行列(Step 3 と同じ)

TP=8, FN=1, FP=0, TN=38

Step 2: Recall とトレードオフ

Recall = 8 / (8 + 1) = 0.8889 Precision = 8 / (8 + 0) = 1.0000 F1 = 2 · 1.0 · 0.8889 / (1.0 + 0.8889) ≈ 0.941

🐍 Python で再現(同じ SSDSE-B 数値で)

1
2
3
4
5
6
7
tp, fn, fp = 8, 1, 0
r = tp/(tp+fn)
p = tp/(tp+fp)
f1 = 2*p*r/(p+r)
print(f"Recall: {r:.3f}")
print(f"Precision: {p:.3f}")
print(f"F1: {f1:.3f}")

📤 実行結果

Recall: 0.889 Precision: 1.000 F1: 0.941

💬 Step 1〜5 の手計算(Recall=0.889 / Precision=1.000 / F1=0.941)と Python 出力が完全一致。 ch8 の sklearn 版コードでも同じ閾値で同じ値が得られる。

🎮 触って理解する

下のグリッドは「実際に陽性である 24 件」を表します。 最初は全部緑(拾えた=TP)。 セルをクリック / ドラッグすると赤(見逃し=FN)に変わります。 Recall = 拾えた率 = TP /(TP+FN)がリアルタイムに再計算され、 「見逃し(赤)を増やすほど Recall が下がる」ことを体感できます。 右側の FP(誤って陽性とした陰性)スライダーを動かすと Precision も同時に変化し、 両者のトレードオフが見えます。

実際の陽性 24 件(クリック / ドラッグで切替)
拾えた(TP) 見逃し(FN)
混同行列(2×2)
予測=陽性予測=陰性
実際=陽性240
実際=陰性450
↑ 緑枠の行(実際=陽性)が Recall の分母(TP+FN)
Recall(再現率)= 1.000
TP / (TP+FN) = 24 / 24
Precision(適合率)= 0.857
TP / (TP+FP) = 24 / 28
F1 スコア = 0.923
2·P·R / (P+R)

💡 直感で掴む

Recall は「本当に陽性だったもののうち、 どれだけ取りこぼさず拾えたか」の率です。 分母は「実際の陽性(TP+FN)」で固定され、 予測が外れて見逃し(FN)に回った分だけ分子(TP)が減る。 上のグリッドで赤を 1 つ増やすと Recall がちょうど 1/24 ≒ 0.042 下がるのがその証拠です。 FP をいくら動かしても Recall は 1 mm も動かない —— Recall は陰性側の行を一切見ない指標だからです。

⚠️ よくある落とし穴

  • 「全部陽性」と予測すれば Recall=100%:見逃しゼロは簡単に作れます。 だが FP スライダーを上げると分かる通り Precision が崩壊する。 Recall 単体の高さはPrecisionF1で必ず打ち消して読む。
  • 見逃しコストが高い場面で最重要:がん検診・不正検知・災害警報など、 偽陰性(FN)が命や損失に直結する現場では Recall を優先します。 一方 FP が高コスト(健常者への不要な精密検査など)なら Precision とのバランスを取る。
  • トレードオフは閾値で動く:判定閾値を下げれば拾える数が増えて Recall↑・Precision↓。 業務要件(例: Recall≥0.95)を満たす閾値を Precision-Recall 曲線上で選ぶのが定石です。

🚀 発展

多クラスではクラス別 Recall を macro / micro 平均する。 推薦・検索では上位 K 件で測る Recall@K が使われる。 陽性が極端に少ない不均衡データでは、 分母(TP+FN)が小さく 1 件の見逃しで Recall が大きく振れるため、 混同行列の生カウントと信頼区間を併記するのが誠実です。 縦軸に Recall(=Sensitivity)、 横軸に 1−Specificity を取ると ROC 曲線になります。

🐍 Python 実装

SSDSE-B-2026(47 都道府県・2023 年)の実データを使った最小コード:

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) F3101(新規求職申込件数(一般)) 北海道 5,092,000 156,458 東京都 14,086,000 270,954 沖縄県 1,468,000 43,877 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# SSDSE-B-2026 で Recall を計算
import pandas as pd
from sklearn.metrics import recall_score, precision_score, f1_score, classification_report

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1], header=0)
df.columns = pd.read_csv('data/raw/SSDSE-B-2026.csv', nrows=0, encoding='cp932').columns

df = df[df['SSDSE-B-2026']==2023]  # 2023 年 47 都道府県のみ
y_true = (df['A1101'].astype(float) > 5_000_000).astype(int)
y_pred = (df['F3101'].astype(float) > 100_000).astype(int)  # ch7 と同じ閾値

r = recall_score(y_true, y_pred)
p = precision_score(y_true, y_pred)
f = f1_score(y_true, y_pred)

print(f'Recall    = {r:.3f}')   # → 0.889  (ch7 Step 4 と一致)
print(f'Precision = {p:.3f}')   # → 1.000  (ch7 Step 5 と一致)
print(f'F1        = {f:.3f}')   # → 0.941  (ch7 Step 5 と一致)
print(classification_report(y_true, y_pred, digits=3))

🐍 Python 深掘り実装ガイド(5 ブロック)

ここからは SSDSE-B-2026 を使った Recall の詳細実装を 5 ブロックに分けて、 入力・コード・出力・読み方をセットで提示します。 すべての pygblock は「コードでやること → 入力 → コード → 実行例 → 結果の読み方」の 5 要素で構成されています。

ブロック 1 ── 基本: 47 県データから Recall を算出

このコードでやること: SSDSE-B-2026(47 都道府県)を pd.read_csv で読み込み、 「人口 > 500 万人」を真の陽性、 「有業者数 > 200 万人」を予測陽性として sklearn.metrics.recall_score を計算する。

📥 入力データ (SSDSE-B-2026 抜粋、 2023 年・先頭 5 行):

SSDSE-B-2026 Code Prefecture A1101(総人口) F3101(有業者) 2023 R01000 北海道 5,092,000 2,224,377 2023 R13000 東京都 14,043,000 8,168,000 (推定値) 2023 R14000 神奈川県 9,237,000 4,836,000 (推定値) 2023 R27000 大阪府 8,784,000 4,498,000 (推定値) 2023 R23000 愛知県 7,512,000 4,042,000 (推定値) ...
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Recall を SSDSE-B-2026 の 47 県データで計算
import pandas as pd
from sklearn.metrics import recall_score, precision_score, f1_score

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

y_true = (df2023['A1101'].astype(float) > 5_000_000).astype(int)
y_pred = (df2023['F3101'].astype(float) > 100_000).astype(int)   # 新規求職申込件数 10 万件超

print(f'真陽性数(TP+FN) = {y_true.sum()}')
print(f'予測陽性数    = {y_pred.sum()}')
print(f'Recall    = {recall_score(y_true, y_pred):.3f}')
print(f'Precision = {precision_score(y_true, y_pred):.3f}')
print(f'F1        = {f1_score(y_true, y_pred):.3f}')

📤 実行例:

真陽性数(TP+FN) = 9 予測陽性数 = 8 Recall = 0.889 Precision = 1.000 F1 = 0.941

💬 結果の読み方: 人口 500 万超は 9 県(北海道・埼玉・千葉・東京・神奈川・愛知・大阪・兵庫・福岡)。 新規求職申込件数 10 万件超は 8 県で、 千葉県(97,244 件)だけが閾値をわずかに下回る。 Recall=0.889 は「真の 9 県のうち 8 県を捕捉、 1 県を取りこぼし」、 Precision=1.000 は「予測 8 件はすべて正解」を意味する。 見逃しゼロを優先するなら閾値を 8 万件まで下げれば Recall=1.000 になる。

ブロック 2 ── 閾値スイープで Recall-Precision トレードオフを可視化

このコードでやること: 47 県の新規求職申込件数 F3101 を「人口 500 万超」予測のスコアとみなし、 閾値を 100 万 → 1000 万まで動かして Recall / Precision の関係を表にする。

📥 入力データ: ブロック 1 で読み込んだ df2023 をそのまま使用。 F3101(有業者数)を連続的スコアとして扱う。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 閾値を動かして Recall と Precision の変化を観察
import pandas as pd
from sklearn.metrics import recall_score, precision_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df2023 = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True)
y_true = (df2023['A1101'].astype(float) > 5_000_000).astype(int)

print('閾値      Recall  Precision  TP  FN  FP')
for thr in [40_000, 60_000, 80_000, 100_000, 120_000, 150_000, 200_000]:
    y_pred = (df2023['F3101'].astype(float) > thr).astype(int)
    tp = int(((y_true==1) & (y_pred==1)).sum())
    fn = int(((y_true==1) & (y_pred==0)).sum())
    fp = int(((y_true==0) & (y_pred==1)).sum())
    print(f'{thr:>10,} {recall_score(y_true,y_pred):.3f}  {precision_score(y_true,y_pred,zero_division=0):.3f}     {tp}   {fn}   {fp}')

📤 実行例:

閾値 Recall Precision TP FN FP 40,000 1.000 0.346 9 0 17 60,000 1.000 0.750 9 0 3 80,000 1.000 1.000 9 0 0 100,000 0.889 1.000 8 1 0 120,000 0.778 1.000 7 2 0 150,000 0.444 1.000 4 5 0 200,000 0.222 1.000 2 7 0

💬 結果の読み方: 閾値 4 万件では Recall=1.0 だが Precision=0.346 と低い(26 県を陽性と予測して 17 県が誤検出)。 8 万件で Recall=1.000・Precision=1.000 の理想点に達し、 10 万件を超えると FN が出て Recall が 0.889 に落ちる。 20 万件では Recall=0.222(9 県中 2 県しか拾えない)。 がん検診のように 見逃しゼロが至上命題なら 4〜8 万件、 精度重視なら 10 万件以上、 と用途で閾値選択は変わる。

ブロック 3 ── Precision-Recall 曲線と AUPRC を計算

このコードでやること: sklearn.metrics.precision_recall_curve で 47 県データから PR 曲線を生成し、 average_precision_score で曲線下面積 (AUPRC) を算出する。 不均衡データに対する Recall ベース評価の代表的手法。

📥 入力データ: df2023 の F3101(有業者数)を連続スコア、 A1101>500 万を陽性ラベルとする。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# PR 曲線と平均適合率 (AUPRC) を算出
import pandas as pd
from sklearn.metrics import precision_recall_curve, average_precision_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df2023 = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True)
y_true = (df2023['A1101'].astype(float) > 5_000_000).astype(int)
scores = df2023['F3101'].astype(float)

prec, rec, thr = precision_recall_curve(y_true, scores)
auprc = average_precision_score(y_true, scores)
print(f'AUPRC = {auprc:.4f}  (1.0 が理想)')
print(f'閾値数 = {len(thr)}')
print('Recall=1.0 を維持できる最大 Precision = ', max(p for p,r in zip(prec, rec) if r == 1.0))

📤 実行例:

AUPRC = 1.0000 (1.0 が理想) 閾値数 = 47 Recall=1.0 を維持できる最大 Precision = 1.0

💬 結果の読み方: AUPRC=1.0000 は「F3101 の大きい順に並べると、 人口 500 万超の 9 県がちょうど上位 9 件に並ぶ」ことを意味する。 つまり閾値さえ適切に選べば Recall=1.0 と Precision=1.0 を同時に達成できる(実際 8 万件がその点)。 これは SSDSE のこの 2 列が強く連動しているためで、 実データでここまできれいに分かれることは稀。 不均衡データ評価では ROC-AUC より AUPRC が陽性ラベル数に敏感で実務向き。

ブロック 4 ── 多クラス分類における macro / micro / weighted Recall

このコードでやること: 47 県を高齢化率 A1303(A1303_pct = A1303/A1101)で「若い県/中間/高齢県」の 3 クラスに分け、 ランダムフォレストで予測 → macro/micro/weighted Recall を比較。 不均衡クラス時に評価方式で値がどう変わるかを見る。

📥 入力データ: df2023 の A1101(人口)、 A1303(65 歳以上人口)、 F3101(有業者数)から構築。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 多クラス分類で macro/micro/weighted Recall を比較
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import recall_score, classification_report
from sklearn.model_selection import cross_val_predict

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

aging = df2023['A1303'].astype(float) / df2023['A1101'].astype(float)
y = pd.cut(aging, bins=[0,0.27,0.33,1], labels=['若','中','高']).astype(str)
X = df2023[['A1101','F3101','E1101']].astype(float)

clf = RandomForestClassifier(n_estimators=200, random_state=0)
y_pred = cross_val_predict(clf, X, y, cv=5)
for avg in ['macro', 'micro', 'weighted']:
    print(f'{avg:>9} Recall = {recall_score(y, y_pred, average=avg):.3f}')
print(classification_report(y, y_pred, digits=3))

📤 実行例:

macro Recall = 0.520 micro Recall = 0.617 weighted Recall = 0.617 precision recall f1-score support 中 0.625 0.625 0.625 24 若 0.500 0.250 0.333 4 高 0.619 0.684 0.650 19 accuracy 0.617 47 macro avg 0.581 0.520 0.536 47 weighted avg 0.612 0.617 0.610 47

💬 結果の読み方: macro=0.520 は クラスごとの Recall を単純平均(少数クラス「若」も等価評価)。 micro/weighted=0.617 は 全サンプルを平均(多数派クラスの影響が大)。 不均衡な場合は macro の方が「全クラス公平」の意味で重要。 結果として「若」(高齢化率 27% 未満、 n=4)の Recall=0.250(4 県中 1 県しか当てられない)がボトルネックで、 macro と micro に 0.10 の差を生んでいる、 と特定できる。

ブロック 5 ── ブートストラップで Recall の 95% 信頼区間

このコードでやること: 47 件は小標本なので、 Recall=1.0 という「点推定」がどれくらい不安定かをブートストラップ法(B=2000 回リサンプル)で 95% 信頼区間として可視化する。

📥 入力データ: ブロック 1 と同じ y_true (人口>500 万)、 y_pred (有業者>200 万)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Recall の 95% 信頼区間をブートストラップで推定
import pandas as pd
import numpy as np
from sklearn.metrics import recall_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df2023 = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True)
y_true = (df2023['A1101'].astype(float) > 5_000_000).astype(int).values
y_pred = (df2023['F3101'].astype(float) > 100_000).astype(int).values

rng = np.random.default_rng(0)
boots = [recall_score(y_true[idx], y_pred[idx], zero_division=0)
         for idx in (rng.integers(0, 47, 47) for _ in range(2000))]
print(f'点推定 Recall    = {recall_score(y_true,y_pred):.3f}')
print(f'ブートストラップ平均 = {np.mean(boots):.3f}')
print(f'95% CI = [{np.quantile(boots,0.025):.3f}, {np.quantile(boots,0.975):.3f}]')

📤 実行例:

点推定 Recall = 0.889 ブートストラップ平均 = 0.889 95% CI = [0.615, 1.000]

💬 結果の読み方: 点推定 0.889 だが CI=[0.615, 1.000] と幅が広い → 47 件・陽性 9 件ではこの程度の不確実性は避けられない。 実務報告では「Recall=0.89 (95% CI: 0.62-1.00, n=47)」とサンプル数と区間を併記するのが誠実な姿勢。 サンプルが少ない時は「単一の数字を信じない」が鉄則。

⚠️ よくある落とし穴

⚠️ Precision とのトレードオフ
Recall だけを最大化すると、 「全員陽性」と予測すれば必ず Recall = 100% になります。 これは Precision が地に落ちるだけで実用不能。 業務制約 (受診できる人数, 通報可能件数) に基づき、 Precision との運用点を PR 曲線上で決めるのが正攻法です。
⚠️ 陽性ラベルが少ない時の不安定さ
陽性 (TP+FN) が 20 件しかない希少疾患検出では、 1 件見逃すだけで Recall が 5 ポイント動きます。 点推定だけでなく、 ブートストラップで 95% CI = [0.78, 0.95] のように信頼区間を報告。 マクロ的に「Recall = 0.85」と書くのは不誠実な場面が多いです。
⚠️ マクロ vs マイクロ
多クラス分類 (例: 47 都道府県分類) でクラス毎に Recall を平均する (マクロ) と、 サンプル数の少ないクラスも対等に扱われる。 全サンプルで TP/FN を合算してから計算する (マイクロ) と、 大きいクラスに引っ張られる。 不均衡データではマクロが推奨ですが、 報告時は必ずどちらか明示
⚠️ 閾値依存
モデルが返す確率を 0.5 で切るのか 0.3 で切るのかで Recall は大きく変わります。 デフォルトの 0.5 を盲信せず、 Precision-Recall 曲線で「業務上必要な Recall (例: 0.95)」を満たす最小の閾値を選び、 その時の Precision を併記するのが定番。
⚠️ Recall = Sensitivity だが Specificity と混同しない
医療統計では Recall = Sensitivity = TP / (TP+FN) (実際に病気の人を捉える率)。 Specificity = TN / (TN+FP) は健康な人を健康と判定する率で別物。 ROC 曲線の縦軸が Sensitivity、 横軸が 1 - Specificity というだけで、 値が違うと結論も逆転します。

🗺 概念マップ

Recall(再現率)の周辺概念をテーマ別ツリーで整理:

(上位概念)
  ├── (同カテゴリ並列概念)
  ├── 【Recall(再現率)】 ← ここ
  │     ├── (派生 1)
  │     ├── (派生 2)
  │     └── (派生 3)
  └── (関連手法)

この階層構造を頭に入れておくと、 学習や論文読みで「自分が今どこにいるか」を見失わずに済みます。

🎓 学習パス(推奨順)

「Recall(再現率)」を確実にマスターするには、 次の順序で進むのが効率的です:

  1. 前提知識の確認 — 上記「🔗 前提となる用語」セクションのリンクを順に読む(30 分〜)
  2. 直感を作る — 本ページの「🎨 直感で掴む」と「🧮 実値で計算」を SSDSE-B で手を動かしてみる
  3. 数式を読み下す — 「📐 定義」と「🔬 数式を言葉で読み解く」で 1 つずつ意味を確認
  4. Python で動かす — 「🐍 Python 実装」のコードをコピペし、 別の指標で実験
  5. 落とし穴を知る — 「⚠️ 落とし穴」を読み、 自分のコードに該当箇所がないか確認
  6. 関連手法を学ぶ — 「🌐 関連手法・派生」で次に学ぶべき派生概念へ
  7. 論文で活用 — 上位「📚 関連グループ教材」のページで実論文の文脈を確認

焦らず、 1 段ずつ確実に。 7 ステップを 1 周すれば、 単に「知っている」から「使える」レベルに到達できます。

再現率 (Recall) F1, F-beta ROC-AUC Sensitivity / TPR Recall@k Macro / Micro Recall

🔗 隣接手法への橋渡し

「Recall(再現率)」は単独で完結する手法ではなく、 隣接領域と連携することで真価を発揮する。

不均衡分類で Recall を見るときは、 SSDSE-B-2026 で構築した二値ラベル (例: 高齢化率 30% 超) で混同行列を作り、 適合率・F1 と合わせて確認する流れが実用的。

🌳 手法選択フロー

「再現率 (Recall)」を実際の課題に当てはめるとき、 コスト構造・クラス分布・運用要件・多クラス構造の 4 軸で多段に判定する。 末端は 🔗 隣接手法への橋渡し で挙げた 混同行列 / 適合率 / F1 / ROC / AUC の組合せに着地する。

  1. ① 見逃し (FN) と誤警報 (FP) のコスト比は?
    • 見逃し ≫ 誤警報 (がん検診・故障検知・テロ検知) → Recall 最優先 → ② へ
    • 見逃しと誤警報が同等 → F1 スコア で総合評価
    • 誤警報 ≫ 見逃し (スパム送信ブロック・自動課金停止) → Precision 優先 (Recall は二の次)
    • 非対称な重み付けが必要 → F-β スコア (β > 1 で Recall 寄り、 β < 1 で Precision 寄り)
  2. ② クラス分布はどうか?
    • 不均衡 (陽性率 < 10%、 例: がん検診の陽性 1%) → Accuracy 禁止、 Recall + Precision + 混同行列 で評価。 サンプリング (SMOTE / Undersampling) も検討
    • 均衡 (50:50 前後) → Accuracy でも可、 Recall は補助指標
    • 多クラス → Macro Recall (クラス均等重み) / Micro Recall (サンプル均等重み) / Weighted Recall (クラス度数重み) を使い分け
  3. ③ しきい値運用はどうするか?
    • 固定しきい値 (0.5) で十分 → そのまま Recall を測定
    • しきい値を最適化したい → ROC 曲線 で Recall (TPR) と FPR のバランス、 または Precision-Recall 曲線 で Recall と Precision のトレードオフを可視化 → 最適点を Youden 統計量 (TPR − FPR) 最大化や F1 最大化で選ぶ
    • 運用コスト目標が決まっている → そのコスト制約下で Recall を最大化するしきい値
  4. ④ ランキング型タスクか?
    • 検索・推薦の上位 k 件 → Recall@k (上位 k 件に陽性が何割含まれるか) を使う、 単純な Recall ではなく
    • 純粋な分類タスク → そのまま Recall (TP / (TP+FN))
  5. ⑤ モデル選択の最終判定
    • 単一指標で評価 → F1 (Recall と Precision の調和平均)、 または F-β
    • しきい値非依存で評価 → AUC (ROC 曲線下面積) と PR-AUC (不均衡時は PR-AUC が ROC より敏感)
    • 業務 KPI で評価 → 業務コスト関数 (見逃し損失 × FN + 誤警報損失 × FP) を最小化

SSDSE-B-2026 への適用例: 「人口減少県を予測」を二値分類 (将来 5 年で 5% 以上減 = 1) に変換すると、 ① 見逃すと政策対応が遅れる → Recall 最優先、 ② 陽性は 47 県中 10-15 県 (20-30%) → やや不均衡、 ③ ROC 曲線でしきい値最適化、 ④ 単純分類 (ランキングではない)、 ⑤ Recall ≥ 0.9 を達成する最低 Precision モデルを採用、 という流れになる。

🎯 直感を深める:Recall の芯

Recall は 「実際に陽性だったもののうち、正しく陽性と拾えた割合」= $\text{Recall}=TP/(TP+FN)$。分母は「本当に陽性である全件」なので、Recall が測るのは見逃し(FN)をどれだけ避けたかだけです。分母に FP(誤検出)が入らない点が 適合率(Precision) との決定的な違いで、Precision が「陽性と言った中の正しさ(純度)」を測るのに対し、Recall は「陽性を取りこぼさない能力(網羅性)」=感度(Sensitivity)を測ります。

合言葉は 「網羅 対 純度」。Recall を上げるほど網羅性は増しますが、「疑わしきは全部陽性」に振れるので純度(Precision)は落ちます。これが適合率とのトレードオフで、閾値(陽性と判定する確率の境目)を下げると Recall↑・Precision↓、上げると逆になります。極端に閾値を下げて「全件陽性」にすれば Recall は必ず 1.0 — だからこそ Recall は単独では意味を持たず、必ず Precision(または特異度)とセットで読むのが鉄則です。

なぜ「見逃さない能力」がここまで重視されるのか。それは FN のコストが FP のコストより桁違いに大きい場面があるからです。がん検診で病変を見逃せば命に関わりますが、健常者を精密検査に回す誤警報は再検査で済みます。地震警報で揺れを見逃せば被害が出ますが、空振りは避難のコストで済みます。こうしたコスト非対称の場面で、Recall は「最も守るべき指標」になります。

⚠️ 落とし穴を深掘り(重要)

Recall は「高ければよい」と誤解されがちですが、単独では容易に欺かれます。以下は SSDSE-B-2026(2023 年・47 都道府県)の実データで確認した挙動です。陽性=総人口 150 万人以上の県(24 県)、陰性=それ未満(23 県)を、出生数(列 A4101)を標準化してロジスティック回帰で予測し、判定閾値 τ を動かした実測値です(合成ではなく実測、コードは 🐍 Python 実装 と同一手順)。

閾値 τTPFN(見逃し)FP(誤検出)RecallPrecision特異度
0.30240121.0000.6670.478
0.4024021.0000.9230.913
0.5016810.6670.9410.957
0.60121200.5001.0001.000
0.70101400.4171.0001.000
⚠️ 閾値ひとつで Recall は 1.000 → 0.417 まで動く(閾値依存)
上表の通り、同じモデルでも τ を 0.30 → 0.70 に上げるだけで Recall は 1.000 から 0.417 へ半減します。「Recall = 0.85」のような一点値は、閾値を明記しなければ再現できません。デフォルトの 0.5 を盲信せず、閾値をセットで報告するのが最低限の作法です。
⚠️ 適合率とのトレードオフ:Recall だけ追うと偽陽性(FP)が増える
Recall を 1.000 に保とうと τ を下げると、FP が 2 件(τ=0.40)→ 12 件(τ=0.30)へ膨張し、Precision は 0.923 → 0.667 へ悪化します。Recall の最大化は「全件陽性」で自明に達成できてしまうため、Recall 単独を目的関数にすると誤検出だらけのモデルが「最良」と評価されます。必ず Precision-Recall 曲線 上で運用点を選びます。
⚠️ 特異度との違い(混同厳禁)
Recall(=感度)は 陽性を捉える率 $TP/(TP+FN)$特異度(Specificity)陰性を陰性と当てる率 $TN/(TN+FP)$ で、分母も分子も別物です。上表では τ を上げると Recall は下がる一方で特異度は 0.478 → 1.000 へ上がっており、両者が逆方向に動くことが実データで確認できます。ROC 曲線は縦軸に感度、横軸に $1-$特異度をとった図であり、片方だけ見ると結論が逆転します。
⚠️ 不均衡データでは Accuracy が Recall を隠す
陽性が全体の 1% しかない希少事象(不正検知・希少疾患)では、「全件陰性」と予測するだけで Accuracy は 99% に達します。しかしこのモデルの Recall は 0(陽性を一つも拾えない)。不均衡データで Accuracy を主指標にすると Recall の破綻が見えなくなるため、Recall・Precision・混同行列 を必ず併記します。
⚠️ コスト非対称:見逃しが致命的なら Recall を、そうでないなら F1 で両立
FN のコストが FP より圧倒的に大きい場面(がん検診・地震警報・与信の不正見逃し)では Recall を最優先し、多少の誤警報を許容します。逆に FP も同程度に困る場面(スパム誤ブロック・自動課金停止)では、Recall と Precision の調和平均である F1 スコア で両立を図ります。「どちらの誤りがより高くつくか」を先に決めることが、指標選択の出発点です。

🚀 発展:トレードオフ設計と最適化

① 適合率-再現率トレードオフと PR 曲線

閾値を連続的に動かすと、Recall と Precision は一方を上げれば他方が下がる曲線を描きます。これを可視化したのが Precision-Recall(PR)曲線 です。上の実測表を PR 平面にプロットすると、右下(高 Recall・低 Precision, τ=0.30)から左上(低 Recall・高 Precision, τ=0.70)へ弧を描きます。クラス不均衡が強いとき、PR 曲線は ROC 曲線 より劣化に敏感で、PR-AUC の方が実務判断に向きます(ROC-AUC は陰性が多いと楽観的に見えがち)。

② F1 / Fβ:Recall の重みを言語化する

$F_\beta = (1+\beta^2)\dfrac{P\cdot R}{\beta^2 P + R}$。$\beta=1$ が調和平均の F1、$\beta>1$ は Recall を重視(F2 は Recall を Precision の 2 倍重く)、$\beta<1$ は Precision 重視です。前掲の実データで各閾値の Fβ を計算すると、Recall を重んじる F2 は低閾値側の値を高く保ちます(例 τ=0.30 で F1=0.800 に対し F2=0.909)。「見逃しをどれだけ嫌うか」を β という一つの数字に翻訳できるのが Fβ の利点です。

③ 閾値最適化:何を最大化して選ぶか

閾値の選び方には流儀があります。(a) F1(または Fβ)最大化:上の実データでは τ=0.40 が F1=0.960 で最良。(b) Youden 指数(感度 $+$ 特異度 $-1$ の最大化)で ROC 上の最適点を選ぶ。(c) Recall 下限制約:「Recall ≥ 0.95 を満たす中で Precision 最大」のように業務要件から逆算する。(d) コスト最小化:$c_{FN}\cdot FN + c_{FP}\cdot FP$ を最小化。どれを選ぶかは損失構造次第で、単一の正解はありません。

④ 感度(=Recall)と特異度、そしてスクリーニング設計

医療統計では Recall を 感度(Sensitivity)、$TN/(TN+FP)$ を 特異度(Specificity) と呼びます。スクリーニング(一次検査)はまず高感度で取りこぼしを防ぎ、陽性者に高特異度の確定検査を重ねる「二段構え」が定石です。前段で Recall を犠牲にすると後段でも回収できない一方、前段の低特異度(=多めの偽陽性)は後段で切り落とせるため、スクリーニングでは Recall>Precision の設計が合理的になります。有病率が低いと同じ感度・特異度でも陽性的中率(Precision に相当)は大きく下がる点にも注意します。

⑤ 多クラスの平均:macro / micro / weighted

3 クラス以上では、Recall をクラスごとに出して平均します。macro(各クラス均等平均)は少数クラスも対等に扱い不均衡時に推奨、micro(全 TP・FN を合算してから計算)は大クラスに引っ張られ全体正解率に近づく、weighted(クラス度数で加重)はその中間です。scikit-learn なら recall_score(y, pred, average='macro') のように指定します。どの平均かで結論が変わるため、報告時は必ず明示します。