F1 Score

Eval

F1スコア | 適合率と再現率の調和平均

作成日: 最終更新: 読了時間: 2 分
まとめ
  • F1 スコアは Precision と Recall の調和平均で陽性検出のバランスを測る指標です。
  • 不均衡データを例に F1 と各構成要素を可視化し、しきい値調整の影響を確認します。
  • Fβ スコアの使い分けや運用時の注意点を整理します。

1. 定義 #

適合率を \(P\)、再現率を \(R\) とすると F1 スコアは F_1 = 2 \cdot \frac{P \cdot R}{P + R} で表せます。より一般的な Fβ スコアは F_\beta = (1 + \beta^2) \cdot \frac{P \cdot R}{\beta^2 P + R} となり、\(\beta > 1\) で再現率を、\(\beta < 1\) で適合率をより重視します。


2. Python 3.13 での計算 #

python --version        # 例: Python 3.13.0
pip install scikit-learn matplotlib
import numpy as np
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (
    classification_report,
    f1_score,
    fbeta_score,
)
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
X, y = make_classification(
    n_samples=40_000,
    n_features=20,
    n_informative=6,
    weights=[0.95, 0.05],
    random_state=42,
)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, stratify=y, random_state=42
)
model = make_pipeline(
    StandardScaler(),
    LogisticRegression(max_iter=2000, class_weight="balanced"),
)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(classification_report(y_test, y_pred, digits=3))
print("F1:", f1_score(y_test, y_pred))
print("F0.5:", fbeta_score(y_test, y_pred, beta=0.5))
print("F2:", fbeta_score(y_test, y_pred, beta=2.0))

classification_report ではクラス別の Precision / Recall / F1 がまとめて確認できます。


3. 閾値と F1 スコアの関係 #

確率出力 predict_proba を使えば、閾値を動かしたときに F1 がどう変わるかを可視化できます。

from sklearn.metrics import precision_recall_curve, f1_score
proba = model.predict_proba(X_test)[:, 1]
precision, recall, thresholds = precision_recall_curve(y_test, proba)
thresholds = np.append(thresholds, 1.0)
f1_scores = [
    f1_score(y_test, (proba >= t).astype(int))
    for t in thresholds
]
F1 スコアと閾値

閾値によって F1 は変動する。Recall を優先したい場合は閾値を下げて再計算する。

  • F1 が最大になる閾値を探せば、Precision / Recall のバランスが最も良い点が分かります。
  • Recall をさらに重視したい場合は F2 や F0.5 といった Fβ スコアで閾値を評価し直すと良いでしょう。

4. 多クラスでの平均化 #

scikit-learn の verage 引数を切り替えることで、多クラス問題でも F1 を集計できます。

  • macro … クラスごとに F1 を計算し単純平均。クラス数が少なくても公平。
  • weighted … クラスごとの F1 をサンプル数で加重平均。全体のバランスを保つ。
  • micro … 混同行列を合算してから計算。クラス不均衡の影響を受けやすい点に注意。
from sklearn.metrics import f1_score
f1_macro = f1_score(y_test, y_pred, average="macro")
f1_weighted = f1_score(y_test, y_pred, average="weighted")

サンプル単位のマルチラベルでは verage=“samples” も利用できます。


まとめ #

  • F1 スコアは適合率と再現率を同じ比重で評価する調和平均。閾値により大きく変動するので可視化して確認する。
  • Fβ スコアを使えば、見逃し重視/誤検知重視など要件に応じて重み付けを変えられる。
  • 多クラスやマルチラベルでは平均化方式を明示し、Precision / Recall / PR 曲線と併せて総合的にモデルの挙動を把握しよう。