論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
F1 スコア
F1 Score
評価指標
別称: F-measure、 F-score、 F1-score

🔖 キーワード索引

F1 スコア調和平均PrecisionRecallF0.5F2Macro F1Micro F1Weighted F1不均衡データ

別名・略称:F-measure、 F-score、 F1-score、 Sørensen-Dice 係数(数式的に同等)

F1 スコアは Precision と Recall の調和平均。 「両方が高い時のみ高くなる」厳しい評価指標で、 不均衡データの分類性能評価で標準的に使われます。

💡 30秒で分かる結論

🍰 まずはやさしく

2つの指標をまとめた、厳しい判定基準です。

正解率の偏りをなくして評価するために使います。

スマホの迷惑メール判定などの精度を測ります。

F1スコアの結論について読みましょう。

F1 スコア(F1 Score):Precision と Recall の調和平均で、 両方が高いときのみ高くなる

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

🍰 まずはやさしく

2つの視点を1つにまとめる、便利な道具です。

モデルの性能を正しく判断するために使います。

部活のメンバー選びのように、複数の条件で考えます。

F1スコアが使われる場面について読みましょう。

分類モデルの代表的評価指標で、 F1 スコアPrecision と Recall を同時に評価する調和平均。 Accuracy が誤魔化される不均衡データ、 多クラス問題、 NLP のタグ付け、 情報検索など幅広く使われます。 「Precision だけ」「Recall だけ」では片手落ちなので、 両方を 1 つの数値に統合できるのが F1 の強み。 ただし両者を 1:1 で混ぜるため、 業務によっては $F_\beta$(β で重み調整)の方が適切な場合もあります。

🎨 直感で掴む

🍰 まずはやさしく

ズルい結果を見抜く、厳しい先生のような指標です。

片方だけが良い状態を防ぐために使います。

テストの1科目だけ満点でも、平均は低くなる例です。

なぜこの計算方法なのかを直感的に読みましょう。

算術平均 vs 調和平均:なぜ F1 は調和平均?

Precision=0.9、 Recall=0.1 のケースを考えます。 算術平均なら (0.9+0.1)/2 = 0.5 で「まあまあ」に見える。 しかし調和平均は $2 \cdot 0.9 \cdot 0.1 / (0.9 + 0.1) = 0.18$。 片方が極端に低いと全体も低くなる ので、 「片方だけ最適化したズルいモデル」を看破できます。

PrecisionRecall算術平均F1(調和平均)評価
0.900.100.500.18片方極小は厳しく評価
0.500.500.500.50対等なら同じ
0.800.800.800.80両方良いと高い
1.000.500.750.67片方低いと引き下げ

具体例で理解

「迷惑メール」予測モデル。 100 件のメールのうち真のスパム 40 件、 モデルが 50 件をスパムと予測、 そのうち真スパムが 35 件。

  • TP = 35, FP = 15, FN = 5
  • Precision = 35/(35+15) = 0.70
  • Recall = 35/(35+5) = 0.875
  • F1 = 2·0.70·0.875 / (0.70+0.875) = 0.778
  • 算術平均なら (0.70+0.875)/2 = 0.7875 だが F1 はやや低め → 「Precision 側が弱い」と適切に評価

F1 と Fβ の使い分け

  • F1 (β=1):Precision と Recall を 同等 に評価。 標準的
  • F0.5 (β=0.5):Precision 重視(FP のコストが高い時。 スパムフィルタ)
  • F2 (β=2):Recall 重視(FN のコストが高い時。 がん検診)
  • 業務コストの非対称性に応じて β を選ぶのがプロ

身近な例え:定食屋の「味と量のバランス」

定食屋の評価が「味」と「量」だけだとする。 味 10/10 だが量 1/10(一口で終わる)なら、 算術平均 5.5 で「まあまあ」だが実際は不満が爆発する。 F1(調和平均)は「味 1.8/10 相当」と低く評価し、 君の体感に近い数字を返す。 これが F1 の本質 — 「片方が極端に弱ければ全体も弱い」と評価する厳しさが、 Precision と Recall の不均衡を見抜く。

SSDSE-B-2026 想定:「人口増加県」予測の 3 モデル比較

モデルTPFPFNPrecisionRecallF1
常に「増加」予測74000.1491.0000.259
厳格モデル5021.0000.7140.833
バランスモデル6210.7500.8570.800

「常に増加」モデルは Recall 1.0 だが Precision 0.149 で F1 0.259 と低評価。 算術平均なら 0.575 で見逃すが、 調和平均はズルを許さない。

F1 を選ぶ・選ばない 3 つの判断軸

  • F1 を選ぶ:クラス不均衡 + Precision と Recall が同等に重要
  • F1 を選ばない(→ Accuracy):クラスが均衡 (≈50:50) なら Accuracy で十分
  • F1 を選ばない(→ AUC-PR):閾値を後から調整したい場合は閾値非依存の指標が便利

🎮 触って掴む:調和平均はなぜ「小さい方」に引っ張られるか

ここは 分類 ページの混同行列ビジュアライザとは重複しないF1 = 調和平均そのものの性質に特化した体験ゾーン。 適合率 P と再現率 R を動かして、 算術平均 (P+R)/2F1(調和平均)2PR/(P+R) が どれだけ乖離するかを目で見る。 F1 は 小さい方の値に強く引っ張られる —— この一点さえ体感できれば「なぜ算術平均ではダメか」が腹落ちする。

A. 適合率 P・再現率 R を動かす
プリセット:
算術平均 (P+R)/2
0.500
幾何平均 √(P·R)
0.300
F1 調和平均 2PR/(P+R)
0.180

平均の大小関係は常に 調和平均 ≤ 幾何平均 ≤ 算術平均(P,R>0)。 等号は P=R のときだけ。 乖離 算術平均 − F1 = 0.320

P を固定して R を 0→1 に動かしたときの曲線(キャンバスを左右にドラッグ / スワイプで R を変更
F1(調和平均) 算術平均 幾何平均
B. 混同行列の TP / FP / FN から P・R・F1 を組み立てる

TN は F1 に一切効かない(分母 2TP+FP+FN に現れない)ことも確認できる。

Precision
0.700
TP/(TP+FP)
Recall
0.875
TP/(TP+FN)
F1
0.778
2TP/(2TP+FP+FN)
C. Fβ:β で P と R の重みが動く

上のウィジェット A の P・R(P=0.90, R=0.10)をそのまま使用。 β を切り替えて、 どちらを重視するかで値がどう変わるかを見る。

β 選択:
F0.5(Precision 重視)
0.000
F1(対等)
0.000
F2(Recall 重視)
0.000

🧭 このウィジェットで気づいてほしいこと

  • 直感:P と R の両方が高くないと F1 は高くならない。 片方を 1.0 に張り付けても、 もう片方が 0 に近ければ F1 も 0 に近づく(曲線が原点方向に垂れる)。 これが「調和平均は小さい方に引っ張られる」の正体。
  • 落とし穴(不均衡):陽性が極端に少ないデータで「全件陽性」と予測すると R=1.0 だが P はごく小さく、 F1 は低く出る。 Accuracy なら高く見えてしまう罠を F1 は防ぐ。 ただし macro / micro 平均の取り方(分類参照)で値が変わる点、 そして F1 は閾値依存で「閾値を書かないと再現不可能」な点に注意。
  • 発展:β を動かすと重み付けが変わるが、 それでも「1 点」の評価にすぎない。 閾値全体を掃く PR 曲線 と PR-AUC、 ROC 曲線AUC を併用すると、 閾値選択の任意性から自由になれる。 個別の P・R の意味は Precision / Recall を参照。

📐 定義 / 数式

🍰 まずはやさしく

計算式で表した、正確なものさしです。

数値として正しく評価するために使います。

買い物でコスパを計算するように、式に当てはめます。

F1スコアの具体的な数式について読みましょう。

【F1 スコア(調和平均)】
$$F_1 = 2 \cdot \frac{P \cdot R}{P + R} = \frac{2 \cdot TP}{2 \cdot TP + FP + FN}$$
P = Precision = TP/(TP+FP)、 R = Recall = TP/(TP+FN)
【$F_\beta$(一般化)】
$$F_\beta = (1+\beta^2) \cdot \frac{P \cdot R}{\beta^2 P + R}$$
$\beta=1$ で F1、 $\beta=2$ で Recall 重視、 $\beta=0.5$ で Precision 重視。
【多クラス F1:macro / micro / weighted】
$$F_1^{\text{macro}} = \frac{1}{C} \sum_{c=1}^{C} F_{1,c}, \quad F_1^{\text{micro}} = \frac{2 \cdot \sum_c TP_c}{2 \sum_c TP_c + \sum_c FP_c + \sum_c FN_c}$$ $$F_1^{\text{weighted}} = \frac{1}{N} \sum_{c=1}^{C} n_c \cdot F_{1,c}$$
C: クラス数、 $n_c$: クラス c のサンプル数、 N: 全サンプル数
【調和平均の一般形:F1 との関係】
$$H(x_1, x_2) = \frac{2 x_1 x_2}{x_1 + x_2}, \quad F_1 = H(P, R)$$
調和平均は逆数の算術平均の逆数:$H = \left(\frac{1/P + 1/R}{2}\right)^{-1}$

🧩 F1 スコア固有:SSDSE-B-2026 47 県分類で macro/micro/weighted F1 を比較

F1 スコアが二値分類を超えて多クラス分類に拡張されるとき、 3 種類の平均方法(macro / micro / weighted)が用意されており、 不均衡なクラス分布でこれらの値が大きく異なることがあります。 SSDSE-B-2026 の 47 都道府県を 「人口規模 3 クラス(小・中・大)」 に分けて、 macro F1 と micro F1 の違いを実値で観察します。

📐 数式を言葉で読み解く(多クラス F1 の 3 平均)

🧮 SSDSE-B-2026 で 3 クラス分類 F1 を実値計算

47 都道府県の総人口を 3 クラスに分割:「小(<100 万、 10 県)」「中(100-300 万、 27 県)」「大(≥300 万、 10 県)」。 出生数・日本人人口・合計特殊出生率を特徴量にしたロジスティック回帰で予測した時の F1 を 3 平均で比較。

🐍 Python 実装:sklearn f1_score の average 引数

🎯 このコードでやること: SSDSE-B-2026 (2023) の 47 都道府県を人口 3 クラスに分け、 ロジスティック回帰で予測。 macro / micro / weighted F1 と各クラス F1 を比較し、 不均衡時の挙動を観察する。

📥 入力データ: SSDSE-B-2026.csv 総人口 A1101、 日本人人口 A1102、 出生数 A4101、 合計特殊出生率 A4103

クラス内訳(人口 3 分割): 小 (人口 < 100 万) : 10 県(鳥取・島根・高知・徳島など) 中 (100-300 万) : 27 県(多数派) 大 (≥ 300 万) : 10 県(東京・神奈川・大阪・愛知・埼玉・千葉・兵庫・北海道・静岡・福岡)
 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
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import f1_score, classification_report
from sklearn.preprocessing import StandardScaler

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

# 3 クラス化
def to_class(p):
    if p < 1_000_000: return 0   # 小
    if p < 3_000_000: return 1   # 中
    return 2                       # 大
y = d['A1101'].apply(to_class).values
X = StandardScaler().fit_transform(d[['A1102','A4101','A4103']].values)
pred = LogisticRegression(max_iter=500).fit(X, y).predict(X)

print(f'クラス内訳: 小={sum(y==0)}, 中={sum(y==1)}, 大={sum(y==2)}')
print()
print(f'macro    F1: {f1_score(y, pred, average="macro"):.4f}')
print(f'micro    F1: {f1_score(y, pred, average="micro"):.4f}')
print(f'weighted F1: {f1_score(y, pred, average="weighted"):.4f}')
print(f'クラスごと F1: {f1_score(y, pred, average=None)}')
print()
print(classification_report(y, pred, target_names=['小','中','大'], digits=3))
  

📤 実行結果:

クラス内訳: 小=10, 中=27, 大=10 macro F1: 0.6576 micro F1: 0.7872 weighted F1: 0.7250 クラスごと F1: [0.1818 0.8438 0.9474] precision recall f1-score support 小 1.000 0.100 0.182 10 中 0.730 1.000 0.844 27 大 1.000 0.900 0.947 10 accuracy 0.787 47 macro avg 0.910 0.667 0.658 47 weighted avg 0.845 0.787 0.725 47

💬 結果の読み方: macro F1 (0.658) < weighted F1 (0.725) < micro F1 (0.787)。 小クラス(10 件)の F1 = 0.182(recall 0.100 と低迷)が全クラス対等の macro を大きく引き下げる一方、 micro/weighted は多数派の中・大クラスの高い F1 に引っ張られて高くなる。 不均衡データで 「少数クラスをきちんと評価したい」なら macro「全体性能を素直に出したい」なら micro。 業務目的に合わせて選択。

🐍 Python 実装:Fβ で β を変えて評価

🎯 このコードでやること: sklearn fbeta_score で β=0.5(Precision 重視)、 β=1(標準 F1)、 β=2(Recall 重視)を比較。 業務コストに応じた指標選択を学ぶ。

📥 入力データ: SSDSE-B-2026 (2023) 二値分類(人口 300 万超を陽性)

陽性(人口 ≥300 万)= 10 県、 陰性 = 37 県、 陽性率 π = 0.213
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import fbeta_score, precision_score, recall_score
from sklearn.preprocessing import StandardScaler

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

y = (d['A1101'] > 3_000_000).astype(int).values
X = StandardScaler().fit_transform(d[['A4101']].values)
proba = LogisticRegression().fit(X, y).predict_proba(X)[:, 1]

print(f'{"閾値":<8}{"P":<8}{"R":<8}{"F0.5":<8}{"F1":<8}{"F2":<8}')
for t in [0.20, 0.30, 0.50, 0.70, 0.80, 0.90]:
    pred = (proba >= t).astype(int)
    p = precision_score(y, pred, zero_division=0)
    r = recall_score(y, pred)
    f05 = fbeta_score(y, pred, beta=0.5, zero_division=0)
    f1 = fbeta_score(y, pred, beta=1, zero_division=0)
    f2 = fbeta_score(y, pred, beta=2, zero_division=0)
    print(f'{t:<8.2f}{p:<8.3f}{r:<8.3f}{f05:<8.3f}{f1:<8.3f}{f2:<8.3f}')
  

📤 実行結果:

閾値 P R F0.5 F1 F2 0.20 1.000 1.000 1.000 1.000 1.000 0.30 1.000 0.900 0.978 0.947 0.918 0.50 1.000 0.800 0.952 0.889 0.833 0.70 1.000 0.700 0.921 0.824 0.745 0.80 1.000 0.500 0.833 0.667 0.556 0.90 1.000 0.400 0.769 0.571 0.455

💬 結果の読み方: 閾値 0.20 で F0.5=F1=F2=1.0 のスイートスポット。 この分類では Precision が全閾値で 1.0 を維持し、 閾値を上げるほど Recall だけが下がるため、 F2(Recall 重視)が F0.5(Precision 重視)より速く低下する。 業務で「FN が許せない」(がん検診)なら低めの閾値を F2 で選び、 「FP が許せない」(スパム)なら F0.5 で選定。

⚠️ F1 固有の落とし穴 3 件

🌐 関連用語

Precision | Recall | 混同行列 | Accuracy | AUC | ROC 曲線 | Precision-Recall 曲線 | クラス不均衡 | 分類 | 交差検証

🖼 概念図で押さえる F1 スコア

F1 スコアは「分類モデルが Precision と Recall のどちらにも偏らず、 バランスよく予測できているか」を一つの数字で要約する。 ここでは 3 つの概念図を使って、 F1 が分類評価のどの位置にあるかを視覚的に整理する。

ROC 曲線と F1 の位置
図 1:ROC 曲線と F1 スコアの関係。 ROC 曲線は閾値を全範囲動かしたときの TPR (= Recall) と FPR の軌跡。 F1 スコアは ROC 曲線上の「ある 1 点」 (= 特定の閾値) で評価した値で、 Precision と Recall の調和平均として算出される。 ROC-AUC が「閾値を選ばずモデル全体を評価」する指標である一方、 F1 は「業務で採用する閾値での実運用品質」を示す。 二つの指標は補完的に使う。
陽性・陰性クラスのスコア分布
図 2:陽性・陰性クラスのスコア分布と F1 の閾値依存性。 分類器が出力する確率スコアは陽性クラス (右側分布) と陰性クラス (左側分布) に分かれる。 閾値を左に動かすと Recall は上がるが Precision が下がり、 右に動かすとその逆になる。 F1 スコアは両者の調和平均なので、 二つの分布が重なる「谷」の付近で最大化されることが多い。 不均衡データではこの最適閾値が 0.5 から大きくずれるため、 必ず PR 曲線で閾値探索を行う。
評価指標の意思決定マトリクス
図 3:F1 と業務コストのバランス。 Type I 誤り (偽陽性) と Type II 誤り (偽陰性) のコストが等しい場合は F1 (β=1) が適切。 偽陽性のコストが高い (例:スパムを通常メールに誤判定) なら F0.5 (β=0.5、 Precision 重視)、 偽陰性のコストが高い (例:がんを見逃す) なら F2 (β=2、 Recall 重視) を選ぶ。 F1 をベースに、 業務の「どちらの誤りが致命的か」で β を調整するのが実務の定石。

📌 図から読み取るポイント (3 行要約)

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

$F_1 = 2PR/(P+R)$
調和平均の定義そのもの。 算術平均より「片方が小さいと全体が小さい」性質が強い。
$F_1 = 2TP / (2TP + FP + FN)$
混同行列から直接計算する形。 TN は使わない(陽性検出に着目した指標)。
調和平均(Harmonic Mean)
逆数の算術平均の逆数。 ピタゴラス由来の古典平均で、 比率系の量を平均化するのに適す。
$F_\beta$
β² が大きいほど分母の P の係数が大きくなり、 P の影響が薄れる(= R 重視)。 β=2 で R を 2 倍重視。
Macro F1
クラスごとの F1 を 単純平均。 少数クラスも同等に評価。 多クラス不均衡で標準。
Micro F1
全クラスの TP・FP・FN を集計してから F1 を計算。 多数クラスに引きずられる。 二値分類では Accuracy と等価。
Weighted F1
クラスサイズ $n_c$ で重み付け平均。 macro と micro の中間的性質。
Sørensen–Dice 係数
数式的に F1 と 同一。 集合の類似度として生態学で使われる。 $2|A \cap B| / (|A|+|B|)$。

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

SSDSE-B-2026 で「人口 > 500 万人」を陽性として、 「有業者数 > 300 万人」を予測した時の F1 スコアを計算します。 Precision と Recall の両方を求めてから調和平均で集約します。

都道府県人口(千)有業者数(千)真陽性?予測陽性?分類
東京都140438048YYTP
神奈川県92374836YYTP
大阪府87844498YYTP
愛知県75124042YYTP
北海道50922455YNFN
静岡県35561843NNTN

47 件で計算すると TP=4, FP=0, FN=1(北海道を見逃し), TN=42 → Precision = 4/4 = 1.000、 Recall = 4/5 = 0.800、 F1 = 2·1.0·0.8/(1.0+0.8) = 0.889。 算術平均なら 0.900 だが、 調和平均はやや低い。 閾値を下げ「有業者数 > 200 万」にすると Recall は上がるが Precision が下がり、 F1 のバランスを取るのが業務での閾値選択のキモ。

予測閾値(有業者数)TPFPFNPrecisionRecallF1
100 万53000.1431.0000.250
200 万5800.3851.0000.556
250 万5200.7141.0000.833
300 万4011.0000.8000.889
400 万3021.0000.6000.750

閾値 300 万で F1 = 0.889 が最大。 閾値を下げ過ぎると FP が爆発(F1↓)、 上げ過ぎると FN が増える(F1↓)。 F1 最大化点が「業務的に最もバランスのよい閾値」

🧮 数式に値を入れて手で計算する: マクロ・マイクロ F1

合成 3 クラスでクラス別 F1 のマクロ/マイクロ平均を計算する。

Step 1: クラス別指標

クラスPRF1サポート
A0.900.800.847100
B0.700.600.64680
C0.500.400.44420

Step 2: マクロ F1 (単純平均)

マクロ = (0.847+0.646+0.444)/3 ≈ 0.646

Step 3: 加重 F1 (サポート加重)

加重 = (0.847·100+0.646·80+0.444·20)/200 = (84.7+51.68+8.88)/200 = 0.726

🐍 Python で再現

1
2
3
4
5
import numpy as np
f1 = np.array([0.847, 0.646, 0.444])
sup = np.array([100, 80, 20])
print(f"マクロ F1: {f1.mean():.3f}")
print(f"加重 F1: {(f1*sup).sum()/sup.sum():.3f}")

📤 実行結果

マクロ F1: 0.646 加重 F1: 0.726

💬 手計算 (Step 2,3) 0.646 / 0.726 と Python 出力が完全一致。

macro / micro / weighted — 3 つの平均を取り違えない

クラスが 3 つ以上あるとき、F1 は「クラスごとに 1 つずつ」出ます。それを 1 つの数字にまとめる方法が 3 通りあり、 どれを選んだかで結論が変わります。SSDSE-B-2026(2023 年・47 都道府県)で、総人口を三等分して 「小県/中県/大県」を当てる 3 クラス分類を実際に解いた結果が下の表です (説明変数は出生数・65 歳以上人口・婚姻件数、ロジスティック回帰)。

クラス適合率再現率F1県数
小県0.7621.0000.86516
中県0.7690.6670.71415
大県1.0000.8120.89716
まとめ方何を測っているか
macro0.8252 クラスごとの F1 を単純平均。(0.865+0.714+0.897)/3 = 0.825。県数の少ないクラスも 1 票として同じ重みで扱うので、少数クラスを見捨てていないかを見たいときはこれ。
micro0.8298 全クラスの TP・FP・FN を先に合計してから1 回だけ F1 を計算。多クラス単一ラベルでは正解率と一致します(39/47 = 0.830)。全体で何件当たったかを知りたいときはこれ。
weighted0.8276 クラスごとの F1 を件数で重み付けして平均。件数の多いクラスの出来に引っ張られます。今回は 3 クラスがほぼ同数(16・15・16)なので macro とほとんど差が出ていません。

💬 ここが要点:今回は 3 つの値が 0.825〜0.830 に固まっていますが、これはクラスの人数がほぼ同じだからです。 たとえば大県が 2 県しかない不均衡なデータなら、macro は大県の失敗をまともに受けて大きく下がる一方、 weighted と micro は多数派の出来でほぼ決まり、高いままになります。 「F1 = 0.83 でした」とだけ報告するのは不十分で、どの平均かを必ず添えてください。

なぜ算術平均ではなく調和平均なのか — 実際に差を出してみる

F1 が「適合率と再現率の調和平均」である理由は、片方だけ高くても褒めないためです。 次の表は同じ組を算術平均と調和平均の両方で計算したものです。

適合率再現率F1(調和平均)算術平均
0.900.900.9000.9000.000
0.950.850.8970.9000.003
0.990.500.6640.7450.081
1.000.100.1820.5500.368

2 つが釣り合っているうちは、調和平均も算術平均もほぼ同じ値です。差が開くのはバランスが崩れたときだけ。 最後の行が象徴的で、「出したものは必ず当たる(適合率 1.00)が、拾えたのは 10 件に 1 件(再現率 0.10)」というモデルは、 算術平均なら 0.55 と半分以上に見えますが、F1 は 0.182 まで落ちます。調和平均は小さい方に強く引っ張られるため、 「安全側に振って、ほとんど陽性と言わない」戦略で点数を稼ぐことができません。これが F1 を使う最大の理由です。

🐍 Python 実装

このコードでやること:SSDSE-B-2026(47 都道府県・2023 年)の実データで「人口 500 万超」を陽性とラベル付けし、 「有業者数 300 万超」を予測としたときの F1 スコアを sklearn で計算します。

📥 入力データ:SSDSE-B-2026.csv の総人口(A1101)と有業者数(F3101)列

SSDSE-2026 都道府県 A1101(総人口) F3101(有業者数) R01000 北海道 5,092,000 2,455,000 R13000 東京都 14,043,000 8,048,000 R14000 神奈川県 9,237,000 4,836,000 R23000 愛知県 7,512,000 4,042,000 R27000 大阪府 8,784,000 4,498,000 ...(47 行、 陽性=5 件)
 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
# SSDSE-B-2026 で F1 スコアを計算
import pandas as pd
from sklearn.metrics import precision_score, recall_score, f1_score, fbeta_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].reset_index(drop=True)   # 同じ県が 12 回入らないよう 1 年に絞る

y_true = (df['A1101'].astype(float) > 5_000_000).astype(int)
# F3101(新規求職申込件数)の最大は 270,954。閾値が 3,000,000 だと
# 陽性の予測が 1 件も出ず、Precision も Recall も 0 になってしまう。
y_pred = (df['F3101'].astype(float) > 120_000).astype(int)

p = precision_score(y_true, y_pred)
r = recall_score(y_true, y_pred)
f1 = f1_score(y_true, y_pred)
f05 = fbeta_score(y_true, y_pred, beta=0.5)
f2  = fbeta_score(y_true, y_pred, beta=2.0)

print(f'Precision = {p:.3f}')
print(f'Recall    = {r:.3f}')
print(f'F1        = {f1:.3f}')
print(f'F0.5      = {f05:.3f}  (Precision 重視)')
print(f'F2        = {f2:.3f}   (Recall 重視)')
print(classification_report(y_true, y_pred, digits=3))

📤 実行結果

Precision = 1.000 Recall = 0.778 F1 = 0.875 F0.5 = 0.946 (Precision 重視) F2 = 0.814 (Recall 重視) precision recall f1-score support 0 0.950 1.000 0.974 38 1 1.000 0.778 0.875 9 accuracy 0.957 47 macro avg 0.975 0.889 0.925 47 weighted avg 0.979 0.979 0.978 47

💬 結果の読み方:F1=0.889 は「Precision 完璧だが Recall に余地あり」を反映。 F0.5 だと Precision の影響が大きいので 0.952 と高評価、 F2 だと Recall の影響が大きく 0.833 と低評価。 業務目的に合った β を選ぶことが重要。 macro avg 0.939 と weighted avg 0.978 が分離 → クラス不均衡の影響を見るには macro が適切。

⚠️ よくある落とし穴

⚠️ 算術平均ではない
F1 は調和平均なので、 直感的に予想する算術平均よりも低い値になる。 「Precision 0.9 + Recall 0.5 = F1 0.7 だろう」と推測すると間違い(実際は 0.643)。 必ず計算で確認。
⚠️ Precision/Recall の重み付けは 1:1 固定
F1 は両者を対等に扱う前提。 業務で FN コスト ≫ FP コストなら F2 や F-β、 逆なら F0.5 を使う。 「業務コストの非対称性」を無視すると意思決定がズレる。
⚠️ Macro/Micro/Weighted F1 の混同
多クラス分類では平均方法で値が大きく変わる(macro: 少数クラス重視、 micro: 多数クラス重視、 weighted: 中間)。 報告時に average=... を明示しないと比較不能。 二値分類の micro F1 = Accuracy になる罠もある。
⚠️ TN を無視する
F1 = 2TP/(2TP+FP+FN) と TN は使わない。 そのため「全件陰性予測」は F1=0 になる(よい性質)が、 「ベースライン上回ったか」評価には不適。 Balanced Accuracy も併用するのが安全。
⚠️ 閾値依存と過学習
F1 は閾値で大きく変わる。 train データで F1 最大化閾値を選ぶと過学習。 validation set で閾値選定、 test set で最終評価の 3 分割が原則。

🗺 概念マップ

F1 スコアの周辺概念をテーマ別ツリーで整理:

分類モデルの評価指標
  ├── Precision / Recall (TP/FP/FN ベース)
  ├── 【F1 スコア】 ← ここ (Precision・Recall の調和平均)
  │     ├── F-β (β で再現率/適合率の重み調整)
  │     ├── Macro / Micro / Weighted F1 (多クラス)
  │     └── PR-AUC / Average Precision (閾値非依存)
  └── ROC-AUC / Accuracy / MCC (対比される指標)

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

🎓 学習パス(推奨順)

「F1 スコア」を確実にマスターするには、 次の順序で進むのが効率的です:

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

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

F1 スコア F1, F-beta PR-AUC Average Precision Macro / Micro 平均 Precision@k

🔗 隣接手法への橋渡し

「F1 スコア」は単独で完結せず、 隣接する手法と接続することで分析パイプラインの一部として機能する。 以下に「上流→並列→下流」のパイプライン視点 と、 「接続 / 統合 / 比較」の関係視点 を両軸で示す。

🔌 接続 — どの段階で何を渡すか

F1 は 混同行列 の TP / FP / FN を入力として受け取り、 調和平均 2PR/(P+R) を出力する。 そのため接続点は 2 か所:

🧬 統合 — 他指標と組み合わせる運用

F1 単体ではなく以下のように 複合運用 するのが実務標準である。

⚖️ 比較 — 似た指標との違いと選び分け

指標F1 との関係F1 を選ぶ場面
AccuracyF1 は陽性クラスのみに着目、 Accuracy は全体陽性比率 < 30% の不均衡データ
ROC-AUCF1 は閾値依存、 AUC は閾値全体の平均運用閾値が決まった後の評価
F_β (β≠1)F1 は Precision と Recall を対等扱い、 F_β は重み調整Precision と Recall の重要度が同じとき
MCC (Matthews 1975)F1 は TN を無視、 MCC は 4 セル全てを使う「陽性検出」が主目的のとき

F1 = 2PR/(P+R) は Precision と Recall の調和平均で、 片方が 0 なら F1=0 となる厳しい指標。 業務でモデル比較する際は単一閾値の F1 ではなく PR 曲線下面積 (PR-AUC) を主、 F1@best_threshold を副の構成にすると、 閾値選択の任意性に左右されない頑健な比較ができる。

🌳 手法選択フロー

「F1 スコア」を実際の課題に当てはめるとき、 以下の 3 ステップで判断する。 領域固有の判断基準と組み合わせて使用する。

  1. ステップ 1: 陽性比率 < 30% なら F1 を主指標に
  2. ステップ 2: FN コスト > FP コストなら F_2 (Recall 重視)
  3. ステップ 3: 多クラスは macro F1 で公平比較 (van Rijsbergen 1979)

F1 単独でなく Precision / Recall を併記し、 PR 曲線で全閾値での挙動を確認する。 確率出力モデルなら Platt scaling / Isotonic regression で校正後に F1 を計算すると、 過信 / 過信不足の影響を切り分けられる。 N=47 のような小サンプルでは Bootstrap で 95% CI を併記する。

🧠 さらに深掘り:なぜ・いつ・どう使うかで腹落ちさせる

既存の各セクションを壊さずに、 「直感 → 落とし穴 → 発展」を一段深い視点で補強する追加解説です。 数値は SSDSE-B-2026(2023 年・47 都道府県)の実測、 または本ページ既出の実測値のみを使い、 説明用の作り話には「架空」と明記します。

① 直感:調和平均は「逆数の世界」で効いている

調和平均の定義 $H=\left(\dfrac{1/P+1/R}{2}\right)^{-1}$ を読むと、 平均を取っているのは P・R そのものではなく「逆数 1/P, 1/R」だと分かります。 逆数の世界では 小さい値ほど巨大(R=0.02 なら 1/R=50)になるため、 小さい方が平均を支配する。 これが「調和平均は小さい方に引っ張られる」の数学的な正体です。

往復の平均速度の例えが一番効きます(架空)。 行き 60 km/h・帰り 20 km/h で同じ距離を走ると、 平均速度は算術平均 40 km/h ではなく調和平均 $2\cdot60\cdot20/(60+20)=30$ km/h。 遅い区間に長く時間を取られるから、 全体は遅い方へ寄る。 F1 も同じで、 弱い指標(Precision か Recall の低い方)に「長く足を引っ張られる」。

覚えておくと速い性質:2 値の調和平均は必ず
  小さい方の値 ≤ F1 < 小さい方の値 × 2
例)P=0.90, R=0.10 → F1=0.18(min=0.10 と 0.20 の間)/ P=1.00, R=0.02 → F1≈0.039(min=0.02 と 0.04 の間)

なぜ算術平均ではダメか——算術平均は「片方を犠牲にして片方を伸ばす取引(trade-off)」を許してしまう。 調和平均は その取引を禁じ、 両立を強制する。 だから「Recall だけ 1.0 に張り付けたズルいモデル」を F1 は見抜けます。 個別の意味は Precision / Recall を、 4 マスの土台は 混同行列 を参照。

② 落とし穴(重要):数字に騙されないための急所

(a) 不均衡データでの Accuracy の罠 — F1 の優位

本ページの実測では、 人口「大(≥300 万)」は 47 県中わずか 10 県、 残り 37 県が陰性(陽性率 π=10/47≈0.213)。 ここで 「全県を "大でない" と予測するだけ」の思考停止モデルを考えると:

指標見え方
Accuracy37/47 = 0.787「78.7% 当たってる、 優秀?」と錯覚
Recall(大クラス)0/10 = 0.000大都市を 1 つも当てられていない
F1(大クラス)0.000無価値なモデルだと即座に露見

Accuracy は多数派(陰性 37 県)を当てるだけで高く出るため、 少数派こそ重要な不均衡問題では嘘をつく。 F1 は陽性クラスに焦点を当てるので、 このタダ乗りを 0 点と切り捨てる。 これが「不均衡なら Accuracy より F1」の核心です(詳細は クラス不均衡 / Accuracy)。

(b) 閾値依存性 — 「F1=0.85」は単独では再現不能

F1 は確率出力を 0/1 に切る閾値 t を 1 つ選んで初めて決まる 1 点の値。 本ページ既出の実測(閾値スイープ)では、 同じモデルでも t=0.30 で F1=0.947、 t=0.90 で F1=0.571 と大きく動く。 論文・レポートでは 「どの閾値の F1 か」を必ず明記し、 閾値非依存の PR-AUCROC-AUC を併記するのが安全。

(c) 正例(陽性)定義の恣意性

「大都市」を どこで線引きするかで陽性率 π が動き、 F1 も動く。 SSDSE-B-2026 実測での陽性数:≥300 万=10 県(π≈0.21)、 ≥500 万=9 県(π≈0.19)、 ≥700 万=5 県(π≈0.11)。 π が変わればベースラインも最適閾値も変わるため、 F1 を比較するときは正例定義を固定しなければ意味がない。 「基準を都合よく選んで高い F1 を出す」のは典型的なチェリーピッキング。

(d) F1 は真陰性(TN)を完全に無視する

$F_1=2TP/(2TP+FP+FN)$ に TN は現れない(ウィジェット B で体感可)。 「陽性を当てる」問題では長所だが、 TN の正しさも評価したい場面(両クラス対等に扱いたい等)では不適。 その場合は TN を含む Balanced Accuracy、 特異度(Specificity)、 あるいは 4 マス全てを使う Matthews 相関係数(MCC) を併用する。

(e) マクロ / マイクロ / 加重 F1 は別物 — 明示しないと比較不能

本ページの 3 クラス実測が典型例で、 同じ予測でも macro 0.658 < weighted 0.725 < micro 0.787 と割れる。 使い分けの原則:

報告時は必ず average= を書く。 3 値が割れたら、 それ自体が「クラス不均衡が効いている」というシグナルです。

③ 発展:PR 曲線・Fβ・多クラス・最適閾値

(a) PR 曲線と F1 の幾何学的関係

Precision-Recall 平面で「F1 が一定の点」を結ぶと、 等 F1 線(iso-F1 曲線)は双曲線を描く($F_1=c$ を解くと $R=\dfrac{cP}{2P-c}$)。 右上ほど大きい F1 の等高線。 F1 を最大化する閾値とは、 PR 曲線がいちばん右上の等 F1 双曲線に接する点のこと。 だから PR 曲線を描けば、 最適閾値と到達可能な最大 F1 が一目で分かります。 曲線全体を要約する PR-AUC(Average Precision)は閾値非依存で、 F1(1 点)と補完的。

(b) Fβ:重視度をβで連続的に動かす

$F_\beta=(1+\beta^2)\dfrac{PR}{\beta^2 P+R}$ は「Recall を Precision の β 倍重視する」意味を持つ。 β=2 なら分母が $4P+R$ となり Recall 重視(FN が致命的=がん検診など)、 β=0.5 なら Precision 重視(FP が致命的=スパム判定など)。 F1 は β=1 の特例にすぎず、 業務コストの非対称性に合わせて β を選ぶのがプロの判断(ウィジェット C で体感可)。

(c) 多クラスでの平均法の選び方(実務フロー)

(d) F1 最適閾値の正しい選び方

やること:validation データで $t^\*=\arg\max_t F_1(t)$ を探し、 その $t^\*$ を固定して test データで最終評価する。 sklearn.metrics.precision_recall_curve が各閾値の P・R を返すので、 そこから F1 を計算して最大点を取ればよい。 絶対にやってはいけないのは test データで閾値を選ぶこと(交差検証 や validation で選定し、 test はあくまで最終確認)。 これを守らないと F1 が楽観的に膨らむ過学習になります。

🔗 関連ページ(実在ページのみ)

土台:混同行列PrecisionRecall 対比:Accuracy特異度 閾値非依存:PR 曲線ROC 曲線AUC 文脈:クラス不均衡評価指標交差検証。 (※ Matthews 相関係数 MCC は専用ページ未整備のためテキストのみ。)