平均化戦略

中級

4.3.14

平均化戦略

最終更新 2020-07-29 読了時間 2 分
まとめ
  • 平均化戦略はマクロ平均やマイクロ平均など複数クラスの指標を集約する考え方です。
  • Python で平均化の違いを算出し、ラベル分布によるスコア差を可視化します。
  • 報告時の平均化選択やラベル比率に応じた注意点をまとめます。

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}}}$$

多クラスの場合、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}$$

少数クラスも多数クラスも等しい重みで扱われます。

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}$$

現実のクラス比率を反映した集約になります。

計算例 #

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 は少数クラスの低いスコアを均等に反映し、Weighted は多数クラスに引っ張られます。


3. Python 3.13 での比較 #

1
2
python --version  # 例: Python 3.13.0
pip install scikit-learn matplotlib
 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 は各クラスの指標と macro avg / weighted avg / micro avg を同時に表示してくれるため、平均化方式の違いをすぐ比較できます。


3. 使い分けのヒント #

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

まとめ #

  • average の選択で同じモデルでも指標の意味合いが大きく変わる。タスクとビジネス要件に合わせて使い分けることが重要。
  • macro はクラス間を公平に、micro は全体の比率を重視、weighted はクラス比を保った平均、samples はマルチラベル専用と覚えておこう。
  • scikit-learn の f1_score などで複数の平均化方式を簡単に計算できるので、併記すると指標の読み違いを防げる。