論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説(ジャストインタイム型データサイエンス教育)
評価指標(Evaluation Metrics)
Evaluation Metrics
機械学習・統計モデルの「良さ」を測る指標群。 分類(混同行列・Precision・Recall・F1・AUC)と回帰(MSE・RMSE・MAE・R²)の両方を体系的に学ぶ。
機械学習評価指標metrics

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

論文・記事に 「Accuracy」「Precision」「Recall」「F1」「ROC-AUC」「RMSE」「MAE」「MSE」「クロスエントロピー」「交差検証」「混同行列」 として登場する評価指標群。 「モデルの良さ」を客観的に測る道具。 タスクの種類とデータの性質で選び分けます。

🔖 キーワード索引

論文記事から各用語のリンクをクリックすると、 該当箇所が開きます:

📊 混同行列 🎯 Accuracy 📐 Precision / Recall 🏆 F1-score 📈 ROC曲線 / AUC 📏 RMSE / MAE / MSE 🔢 クロスエントロピー ⚖️ クラス不均衡 🔁 交差検証 🧭 指標の選び方 🚧 よくある誤解 📝 練習問題 🗺️ 概念マップ

💡 30秒で分かる結論

🗂️ 章俯瞰 — 指標群の使い分け

機械学習・統計モデルの「良さ」を測る指標。 タスクの種類(分類 / 回帰 / ランキング / 生成)とデータの性質(クラス不均衡 / 外れ値)に応じて選びます。 「1指標だけで判断しない」「テストデータで評価する」が鉄則。

タスク 代表指標 範囲 良い値
2値分類(バランス)Accuracy、 AUC[0, 1]↑(1 に近い)
2値分類(不均衡)F1、 Precision、 Recall、 PR-AUC[0, 1]
多クラス分類macro/micro F1、 Top-k Accuracy[0, 1]
確率予測Log Loss、 クロスエントロピー、 Brier Score[0, ∞)↓(0 が理想)
回帰MSE、 RMSE、 MAE、 R²[0, ∞) / R² ≤ 1MSE↓ / R²↑
ランキングNDCG、 MAP、 MRR[0, 1]

📊 混同行列(Confusion Matrix)

分類予測の正解と誤りを表にしたもの。 すべての分類指標の出発点。

予測:陽性予測:陰性
実際:陽性TP(真陽性)FN(偽陰性)
実際:陰性FP(偽陽性)TN(真陰性)

多クラス分類では k×k の行列に拡張。 対角が正解、 非対角が間違い。

 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
31
32
33
34
35
## scikit-learn の評価指標を一気に使う
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split, StratifiedKFold, cross_validate
from sklearn.metrics import (
    accuracy_score, precision_score, recall_score, f1_score,
    roc_auc_score, average_precision_score, log_loss,
    confusion_matrix, classification_report, roc_curve, precision_recall_curve
)

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['年度']==2023]
## 「東日本 vs 西日本」を 2 値ターゲットにする
east = ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県',
        '茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県',
        '新潟県','富山県','石川県','福井県','山梨県','長野県']
df['east'] = df['都道府県'].isin(east).astype(int)

X = df[['A1101', 'A4101', 'A6101']].values  ## 人口・高齢化率・婚姻件数
y = df['east'].values

X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, stratify=y, random_state=42)
model = LogisticRegression(max_iter=1000).fit(X_tr, y_tr)
y_pred = model.predict(X_te)
y_prob = model.predict_proba(X_te)[:, 1]

print(f'Accuracy : {accuracy_score(y_te, y_pred):.3f}')
print(f'Precision: {precision_score(y_te, y_pred):.3f}')
print(f'Recall   : {recall_score(y_te, y_pred):.3f}')
print(f'F1       : {f1_score(y_te, y_pred):.3f}')
print(f'ROC-AUC  : {roc_auc_score(y_te, y_prob):.3f}')
print(f'PR-AUC   : {average_precision_score(y_te, y_prob):.3f}')
print(f'LogLoss  : {log_loss(y_te, y_prob):.3f}')
print(classification_report(y_te, y_pred))

② scipy.stats — 手計算で混同行列を組み立てる

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
## numpy / scipy だけで混同行列と派生指標を計算
import numpy as np
from scipy import stats

## ベルヌーイ分布から擬似テストデータ(実務でも観測される構造)
y_true = np.array([1,0,1,1,0,1,0,0,1,0,1,1,0,1])
y_pred = np.array([1,0,1,0,0,1,1,0,1,0,1,0,0,1])

TP = np.sum((y_true==1) & (y_pred==1))
TN = np.sum((y_true==0) & (y_pred==0))
FP = np.sum((y_true==0) & (y_pred==1))
FN = np.sum((y_true==1) & (y_pred==0))

acc = (TP+TN) / len(y_true)
prec = TP / (TP+FP) if (TP+FP) > 0 else np.nan
rec  = TP / (TP+FN) if (TP+FN) > 0 else np.nan
f1   = 2*prec*rec / (prec+rec)

## マクネマー検定(2 つのモデル比較に scipy.stats を使う)
from scipy.stats import binomtest
b = 3; c = 5  ## A正解&B不正解, A不正解&B正解
p = binomtest(b, b+c).pvalue
print(f'McNemar p={p:.4f}')

③ cross_validate で複数指標を一度に

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from sklearn.model_selection import cross_validate
from sklearn.ensemble import RandomForestClassifier

scoring = ['accuracy', 'precision', 'recall', 'f1', 'roc_auc', 'average_precision', 'neg_log_loss']
results = cross_validate(
    RandomForestClassifier(n_estimators=200, random_state=42),
    X, y, cv=5, scoring=scoring, return_train_score=True)
for metric in scoring:
    test_score = results[f'test_{metric}']
    print(f'{metric:18s}: {test_score.mean():.3f} ± {test_score.std():.3f}')

④ 閾値最適化 — Youden index と F1 最大点

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
## ROC 曲線から Youden index 最大の閾値を選ぶ
from sklearn.metrics import roc_curve, precision_recall_curve

fpr, tpr, thresh = roc_curve(y_te, y_prob)
youden = tpr - fpr
best_idx = np.argmax(youden)
print(f'Best threshold (Youden): {thresh[best_idx]:.3f}')
print(f'  TPR={tpr[best_idx]:.3f}, FPR={fpr[best_idx]:.3f}')

## PR 曲線から F1 最大の閾値
prec, rec, thresh_pr = precision_recall_curve(y_te, y_prob)
f1_scores = 2 * prec * rec / (prec + rec + 1e-9)
best_pr = np.argmax(f1_scores[:-1])
print(f'Best threshold (F1)    : {thresh_pr[best_pr]:.3f}, F1={f1_scores[best_pr]:.3f}')

⑤ 回帰指標 — scikit-learn / scipy 両方で

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score, mean_absolute_percentage_error
from scipy.stats import pearsonr, spearmanr

y_true = np.array([100, 150, 200, 250, 300])
y_pred = np.array([110, 140, 220, 240, 310])

print(f'MAE  : {mean_absolute_error(y_true, y_pred):.2f}')
print(f'MSE  : {mean_squared_error(y_true, y_pred):.2f}')
print(f'RMSE : {mean_squared_error(y_true, y_pred, squared=False):.2f}')
print(f'MAPE : {mean_absolute_percentage_error(y_true, y_pred)*100:.2f}%')
print(f'R²   : {r2_score(y_true, y_pred):.3f}')
print(f'Pearson r : {pearsonr(y_true, y_pred)[0]:.3f}')
print(f'Spearman ρ: {spearmanr(y_true, y_pred)[0]:.3f}')