機械学習の評価指標とPythonでの実装【二値分類 前編】

「効果指標入門」を参考に、機械学習における評価指標をまとめました。今回は二値問題における評価指標を取り上げます。

※内容に間違いがあればご指摘いただけますと幸いです。

# 評価指標とはなにか
機械学習モデルの性能を評価するために使用される「評価指標」とは、モデルがタスクをどれだけ効果的に実行しているかを定量的に測定するための尺度や基準です。

これらの指標は、モデルの訓練やチューニングにおいて不可欠であり、モデルの予測がどれだけ正確で信頼性があるかを評価します。

評価指標は大きく分けて二つのタイプがあります。一つは「分類タスク」のためのもので、もう一つは「回帰タスク」のためのものです。今回は、分類タスクに焦点を当て、その中でも特に「二値分類」における評価指標について説明します。

回帰タスクにおける評価指標は以下にまとめています。
https://qiita.com/pnd642/items/089143957de635df6444

# 分類タスク
機械学習のタスクによって使用される評価指標は異なります。

分類は、ある入力が与えられたときに、その入力がどのカテゴリまたはクラスに属するかを予測するタスクです。分類タスクには主に以下の二つのタイプがあります。

- 二値分類：入力が2つの相互排他的なカテゴリ（例えば、「スパム」または「スパムでない」）のどちらか一方に分類する

- 多クラス分類：入力が2つ以上の相互排他的なカテゴリ（例えば、「赤」、「青」、「緑」）のいずれかに分類する

また、分類のアルゴリズムには様々なものがあり、以下が代表的です。

| アルゴリズム               | 説明                                           |
|--------------------------|----------------------------------------------|
| 決定木                   | データを分割するための一連の質問を使用して、特定のクラスに分類 |
| ロジスティック回帰       | データが特定のクラスに属する確率を予測              |
| サポートベクトルマシン   | データ間のマージンを最大化することで分類      |
| ランダムフォレスト       | 複数の決定木を組み合わせて、より正確な予測を行う       |
| ニューラルネットワーク     | 人間の脳を模倣した複雑なモデル、非常に高次元で複雑なデータセットでも使用可能 |


# 評価指標の分類

評価指標は大きく分けて二つのタイプがあります。一つは「分類タスク」のためのもので、もう一つは「回帰タスク」のためのものです。

今回は、分類タスクに焦点を当て、その中でも特に「二値分類」における評価指標について説明します。

# 分類における評価指標

二値分類では、各インスタンスが正（Positive）または負（Negative）のいずれかのクラスに属すると予測します。

分類タスクでは、以下のような評価指標が一般的に使用されます。

- 正解率（Accuracy）
- 適合率（Precision）
- 再現率（Recall）
- F1-score
- G-Mean
- マシューズ相関係数
- ROC-AUC
- PR-AUC
- pAUC


## 混同行列

混同行列は、モデルがどの程度正確に予測したかを示す表であり、分類モデルの性能評価に用いられます。

表は4つの部分から成り立ち、正解率（Accuracy）、適合率（Precision）、再現率（Recall）、F1スコア（F1 Score）などの評価指標を計算するための基本的な情報を提供します。

|         | 予測 Positive | 予測 Negative |
|---------|----------------|----------------|
| 実際 Positive | True Positive (TP) | False Negative (FN) |
| 実際 Negative | False Positive (FP) | True Negative (TN)  |

各セルの意味は以下の通りです。

- **True Positive (TP)**：モデルが実際に Positive なクラスを正しく予測した数
- **False Negative (FN)**：モデルが実際に Positive なクラスを誤って Negative と予測した数
- **False Positive (FP)**：モデルが実際に Negative なクラスを誤って Positive と予測した数
- **True Negative (TN)**：モデルが実際に Negative なクラスを正しく予測した数

## 正解率

正解率（Accuracy）は、全体の予測のうち正しく予測できた割合を示します。数式で表すと以下のようになります。

$$ Accuracy = \frac{TP + TN}{TP + FP + FN + TN} $$

直感的でわかりやすい指標ですが、不均衡データ（各正解ラベルの出現比率に偏りがあるデータ）では多数派のクラスの影響を受けやすいという欠点があります。

```python:pythonでの算出方法
# 正解率
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_test, y_pred)
print(f"正解率: {round(accuracy, 3)}")
```

## 適合率

適合率（Precision）は、正と予測されたインスタンスのうち実際に正であった割合を示します。数式で表すと以下のようになります。

$$ Precision = \frac{TP}{TP + FP} $$

```python:pythonでの算出方法
# 適合率
from sklearn.metrics import precision_score
precision = precision_score(y_test, y_pred))
print(f"適合率: {round(precision, 3)}")
```

## 再現率

再現率（Recall）は、実際に正であったインスタンスのうち正しく予測できた割合を示します。数式で表すと以下のようになります。

$$ Recall = \frac{TP}{TP + FN} $$

```python:pythonでの算出方法
# 再現率
from sklearn.metrics import recall_score
recall = recall_score(y_test, y_pred)
print(f"再現率: {round(recall, 3)}")
```

## F1-score

F1-scoreは適合率と再現率の調和平均です。数式で表すと以下のようになります。

$$ F1 = 2 \times \frac{Precision \times Recall}{Precision + Recall} $$


```python:pythonでの算出方法
# F1スコア
from sklearn.metrics import f1_score
f1 = f1_score(y_test, y_pred)
print(f"F1スコア: {round(f1, 3)}")
```

## G-Mean

G-Meanは真陽性率と真陰性率の幾何平均です。数式で表すと以下のようになります。

$$ G-Mean = \sqrt{TPR \times TNR} $$

ここで、真陽性率（TPR）= 再現率、真陰性率（TNR）= $\frac{TN}{TN + FP}$ です。

```python:pythonでの算出方法
# G-Mean
import math
from sklearn.metrics import confusion_matrix

def g_mean_score(y, y_pred):
    # 混同行列を作成して各要素を変数に格納する
    tn, fp, fn, tp = confusion_matrix(y, y_pred).ravel()
    # True Positive Rateを算出する
    tp_rate =  tp / (tp + fn)
    print("True Positive Rate:", round(tp_rate, 2))
    # True Negative Rateを算出する
    tn_rate = tn / (tn + fp)
    print("True Negative Rate:", round(tn_rate, 2))
    # G-meanはTrue Positive RateとTrue Negative Rateの幾何平均を計算
    return math.sqrt(tp_rate * tn_rate)

print("G-Mean: ", round(g_mean_score(y_test, y_pred), 3))
```

## マシューズ相関係数

マシューズ相関係数（MCC）は、TP、FP、FN、TNの全てのパターンを評価に加えた指標であり、真のクラスと予測結果の相関係数を示します。数式で表すと以下のようになります。

$$ MCC = \frac{TP \times TN - FP \times FN}{\sqrt{(TP + FP)(TP + FN)(TN + FP)(TN + FN)}} $$

Positive, Negativeの両方に関心がある場合によく用いられ、不均衡なデータでもうまく評価を行うことができます。

```python:pythonでの算出方法
# マシューズ相関係数（MCC）①
## sklearnを利用してマシューズ相関係数を算出する
from sklearn.metrics import matthews_corrcoef
mcc = matthews_corrcoef(y_test, y_pred)
print(f"MCC: {round(mcc, 3)}")

# マシューズ相関係数（MCC）②
## 実際の正解クラスと予測されたクラスを逆にしてマシューズ相関係数を算出する
import numpy as np
mcc = matthews_corrcoef(np.where(y_test == 0, 1, 0), np.where(y_pred == 0, 1, 0))
print(f"MCC: {round(mcc, 3)}")
```

## ROC-AUC

ROC-AUC (Receiver Operating Characteristic - Area Under the Curve): ROC曲線は、分類モデルの性能を評価するためのグラフで、真陽性率（TPR）を偽陽性率（FPR）に対してプロットします。

AUCはROC曲線下の面積を表し、モデルがクラスを区別する能力を示します。AUCが1に近いほど、モデルの予測が正確であることを示します。

```python:pythonでの算出方法
from sklearn.metrics import roc_auc_score

# ラベルが1である予測確率を取得する
y_pred = clf.predict_proba(X_test)[:, 1]

# ROC-AUCを算出する
roc_auc = roc_auc_score(y_test, y_pred)
print(f"ROC-AUC: {round(roc_auc, 3)}")
```

## PR-AUC

PR-AUC (Precision-Recall - Area Under the Curve): PR曲線は適合率（Precision）を再現率（Recall）に対してプロットしたもので、PR-AUCはPR曲線下の面積を表します。

PR-AUCは不均衡なデータセットでも有効で、閾値選択に影響されやすいという特性があります。
```python:pythonでの算出方法
from sklearn.metrics import auc, precision_recall_curve

# ラベルが1である予測確率を取得する
y_prod = clf.predict_proba(X_test)[:, 1]

# 予測確率を使って閾値を操作したPrecisionとRecallとその時の閾値の3つを算出
precision, recall, thresholds = precision_recall_curve(y_test, y_pred)
# AUCを算出する
pr_auc = auc(recall, precision)

print(f"PR-AUC: {round(pr_auc, 3)}")
```

## pAUC

pAUC (Partial Area Under the Curve): pAUCはROC曲線の一部分（特定のFPR範囲）の面積を示し、不均衡なデータセットに対するモデルの性能を評価する際に有用です。

特定のFPR範囲に焦点を当てられるため、部分的な性能評価が可能です。

```python:pythonでの算出方法
from sklearn.metrics import roc_auc_score

# ラベルが1である予測確率を取得する
y_prod = clf.predict_proba(X_val)[:, 1]

# pAUCを算出
p_auc = roc_auc_score(y_test, y_pred, max_fpr=0.2)
print(f"pAUC: {round(p_auc, 3)}")
```


# 各指標まとめ
以下に、分類タスクにおける各評価指標の名称、説明、メリット・デメリットを表にまとめました。

| 評価指標 | 説明 | メリット | デメリット |
|---|---|---|---|
| 混同行列 | モデルがどの程度正確に予測したかを示す | 具体的な予測結果を視覚的に理解できる | モデル全体の性能を一つの数値で表現することはできない |
| 正解率 | 全体の予測のうち正しく予測できた割合を示す | シンプルで直感的 | 不均衡なデータセットでは誤解を招く可能性がある |
| マシューズ相関係数 | 二値分類器の品質を評価するための指標 | 不均衡なデータセットでも有効 | 計算が複雑であり、理解するのが難しい場合がある |
| 適合率 | 正と予測されたインスタンスのうち実際に正であった割合を示す | 偽陽性を重視する場合に有用 | 偽陰性は考慮しないため、再現率が低い場合には問題がある |
| 再現率 | 実際に正であったインスタンスのうち正しく予測できた割合を示す | 偽陰性を重視する場合に有用 | 偽陽性は考慮しないため、適合率が低い場合には問題がある |
| F1-score | 適合率と再現率の調和平均 | 適合率と再現率のバランスを取ることができる | 不均衡なコスト設定では不適切な場合がある |
| G-Mean | 真陽性率と真陰性率の幾何平均 | 不均衡なデータセットでも有効 | 特定のクラスへの重視が難しい場合がある |
| ROC-AUC | 偽陽性率が変化するときの真陽性率をプロットした曲線下面積を示す | 閾値選択に依存しないため、モデル全体の性能を評価できる | 不均衡なデータセットでは誤解を招く可能性がある |
| PR-AUC | 再現率が変化するときの適合率をプロットした曲線下面積を示す | 不均衡なデータセットでも有効 | 閾値選択に影響されやすい |
| pAUC | ROC曲線の一部分（特定のFPR範囲）の面積を示す。これは、不均衡なデータセットに対するモデルの性能を評価する際に有用 | 特定のFPR範囲に焦点を当てられるため、部分的な性能評価が可能 | 全体的な性能評価は難しい場合がある |

今回は指標の説明が長くなったため、Pythonでの実装例は次回の記事で多クラス分類とともにまとめたいと思います。

## 参考文献・参考サイト
・評価指標入門