K_DM Book
用語集
対象者 標準
対象者別の入口 →

対象者の設定はこのブラウザの中にだけ保存されます。

言語 JA

平均化戦略

中級

03.3.14

平均化戦略

最終更新 2020-07-29 読了時間 3 分
まとめ
平均化戦略は、3 クラス以上の分類でクラスごとに出た Precision・Recall・F1 を 1 つの数にまとめる方法で、scikit-learn では f1_score(..., average=...) の引数で選びます。micro は全クラスの TP/FP/FN を合算してから計算するので多クラスでは Accuracy と一致し、macro はクラスごとの値を単純平均するので 5 % しかない少数クラスも 85 % の多数クラスと同じ重みになります。weighted はサンプル数で加重平均するので実データのクラス比を反映し、samples はマルチラベル専用です。同じ予測でも macro F1 が 0.65、weighted F1 が 0.87 のように大きく変わるため、報告するときはどの平均化かを必ず明記します。

適合率・再現率 と F1スコア で二値分類の指標を先に学ぶと、本ページがそれらを多クラスへ広げる話だと分かって理解がスムーズです。


1. 主な平均化の種類 #

average計算方法特徴・主な利用場面
microすべてのサンプルの TP/FP/FN を合算して指標を算出クラスごとの重み付けは行わず、全体の正解率を重視する場合
macroクラスごとに指標を計算し、単純平均少数クラスも同じ重みで扱える。医療・不正検知などで有効
weightedクラスごとに指標を計算し、サンプル数で加重平均実データのクラス比を保ちながら平均を取りたい場合
samplesマルチラベル用。サンプルごとに平均1 件に複数ラベルが付く画像タグ分類などで標準的

2. 数学的定義 #

$K$ クラスの分類で、クラス $k$ の真陽性 $\text{TP}_k$、偽陽性 $\text{FP}_k$、偽陰性 $\text{FN}_k$ を使って定義します。

Micro 平均 #

すべてのクラスの TP/FP/FN を合算してから指標を計算します:

$$P_{\text{micro}} = \frac{\sum_{k=1}^{K} \text{TP}_k}{\sum_{k=1}^{K} (\text{TP}_k + \text{FP}_k)}, \quad R_{\text{micro}} = \frac{\sum_{k=1}^{K} \text{TP}_k}{\sum_{k=1}^{K} (\text{TP}_k + \text{FN}_k)}$$$$F_{1,\text{micro}} = \frac{2 \cdot P_{\text{micro}} \cdot R_{\text{micro}}}{P_{\text{micro}} + R_{\text{micro}}}$$

多クラスの場合、各サンプルは必ず 1 つのクラスに予測されるので、あるクラスの FP は別のクラスの FN として二重に数えられ、$\sum \text{FP}_k = \sum \text{FN}_k$ になります。そのため Micro-F1 は Accuracy(正解率)と一致します。

Macro 平均 #

クラスごとに指標を計算し、単純平均を取ります:

$$P_{\text{macro}} = \frac{1}{K} \sum_{k=1}^{K} P_k, \quad R_{\text{macro}} = \frac{1}{K} \sum_{k=1}^{K} R_k$$$$F_{1,\text{macro}} = \frac{1}{K} \sum_{k=1}^{K} F_{1,k}$$

5 件しかないクラス C も 80 件のクラス A も、$1/K$ という等しい重みで扱われます。

Weighted 平均 #

クラスごとの指標を、そのクラスのサンプル数 $n_k$ で加重平均します:

$$P_{\text{weighted}} = \frac{\sum_{k=1}^{K} n_k \cdot P_k}{\sum_{k=1}^{K} n_k}, \quad R_{\text{weighted}} = \frac{\sum_{k=1}^{K} n_k \cdot R_k}{\sum_{k=1}^{K} n_k}$$$$F_{1,\text{weighted}} = \frac{\sum_{k=1}^{K} n_k \cdot F_{1,k}}{\sum_{k=1}^{K} n_k}$$

80 件のクラスは 5 件のクラスの 16 倍の重みを持つので、現実のクラス比率を反映した集約になります。

計算例 #

3 クラス(A: 80件, B: 15件, C: 5件)で各クラスの F1 が $F_{1,A}=0.95$, $F_{1,B}=0.60$, $F_{1,C}=0.40$ のとき:

平均化計算結果
Macro$(0.95 + 0.60 + 0.40) / 3$0.650
Weighted$(80 \times 0.95 + 15 \times 0.60 + 5 \times 0.40) / 100$0.87

Macro は少数クラス C の 0.40 を 3 分の 1 の重みでそのまま反映し、Weighted は 80 件のクラス A の 0.95 に引っ張られます。同じモデルなのに 0.65 と 0.87 という 0.22 の差が出るのが、平均化を明記すべき理由です。


3. Python 3.13 での比較 #

1
2
python --version  # 例: Python 3.13.0
pip install scikit-learn matplotlib

次のコードは、クラス比 85 : 10 : 5 の 3 クラスデータ 30,000 件にロジスティック回帰を当て、classification_report でクラスごとの指標と、f1_score の micro・macro・weighted を並べて表示します。

 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
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, f1_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=30_000,
    n_features=20,
    n_informative=6,
    weights=[0.85, 0.1, 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, multi_class="ovr"),
)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

print(classification_report(y_test, y_pred, digits=3))
for avg in ["micro", "macro", "weighted"]:
    print(f"F1 ({avg}):", f1_score(y_test, y_pred, average=avg))

実行結果の読み方 #

classification_report のクラス 2(5 % のクラス)の行は、他の 2 クラスより recall と f1-score が目立って低くなります。その下の macro avg はこの低い値を 3 分の 1 の重みで含むので weighted avg より小さく、accuracy の行(= micro F1)は 85 % を占めるクラス 0 の出来にほぼ決まります。少数クラスを見たい場面で weighted や micro だけを報告すると、クラス 2 の取りこぼしが数字に現れません。


4. 使い分けのヒント #

micro はモデルの総合的な正解率を重視したいときに使い、Kaggle などで全サンプルの正答率を確認する感覚に近い値になります。macro は 5 % の少数クラスも同じ重みで扱いたいとき、たとえば医療診断や不正検知のように取りこぼしが許されない場面に向きます。weighted は現実のクラス比 85 : 10 : 5 を保ったまま評価したいときに使い、Accuracy に近い感覚で Precision / Recall / F1 を報告できます。samples はマルチラベル分類で 1 サンプルに複数ラベルが付く性能を測りたいときの標準的な選択です。


まとめ #

average の選択で、同じモデル・同じ予測でも F1 が 0.65(macro)から 0.87(weighted)まで変わります。macro はクラス間を公平に、micro は全体の比率を重視して多クラスでは Accuracy に一致し、weighted はクラス比を保った平均、samples はマルチラベル専用と覚えてください。scikit-learn の f1_score や classification_report で複数の平均化方式を一度に計算できるので、報告では macro と weighted を併記し、差が大きければ少数クラスの混同行列を確認するのが読み違いを防ぐ手順です。