Confusion matrix（混同行列）に要素数とパーセンテージを表示するには？

# 1. Confusion matrix（混同行列）とは？
Confusion matrix（混同行列）は、機械学習においては、構築したモデルの性能を評価する手段のひとつである。

Confusion matrixは、4つの要素から構成される。

|要素|意味|
|:-:|:-:|
|True Positive|実際にポジティブで、モデルもポジティブと予測したもの|
|True Negative|実際にネガティブで、モデルもネガティブと予測したもの|
|False Positive|実際にはネガティブだが、モデルがポジティブと予測したもの|
|False Negative|実際にはポジティブだが、モデルがネガティブと予測したもの|

# 2. PythonでConfusion matrixを作成するには？

## 2.1. サンプルデータの読み込み
今回はScikit-learnにて入手可能なデータセットから「Breast Cancer Wisconsin」を使用する。

~~~Python
# 必要なライブラリのインポート
from sklearn.datasets import load_breast_cancer
import pandas as pd

# Breast Cancer Wisconsinデータセットの読み込み
breast_cancer = load_breast_cancer()

# 特徴量データをDataFrameに変換
df = pd.DataFrame(breast_cancer.data, columns=breast_cancer.feature_names)

# 目的変数（ターゲット）をDataFrameに追加
df['diagnosis'] = breast_cancer.target

# 説明変数と目的変数を分ける
X = df.drop('diagnosis', axis=1)
y = df['diagnosis']

from sklearn.model_selection import train_test_split

# データをトレーニングセットとテストセットに分割
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, stratify=df['diagnosis'], random_state=42)

from sklearn.ensemble import RandomForestClassifier

# モデルの訓練
model = RandomForestClassifier()
model.fit(X_train, y_train)

# 予測
y_pred = model.predict(X_val)
~~~

# 2.2. Confusion matrixの作成

上記の結果に基づいてConfusion matrixを作成する。

## 2.2.1. Confusion matrix作成のシンプルなコード

~~~Python
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay

# Confusion matrixの生成
cm = confusion_matrix(y_val, y_pred)

# Confusion matrixの表示
disp = ConfusionMatrixDisplay(confusion_matrix=cm)
disp.plot(cmap=plt.cm.Blues)

# X軸ラベル、Y軸ラベル、タイトルの追加
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix')

# Confusion matrixの表示
plt.show()
~~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3692239/cce411f1-b95d-897f-b3ee-5248ea51660b.png)

結果を提示する際に、このままでに使用することは可能であるが、通常は各区画のパーセンテージを行の合計に対する割合で示すことが一般的である。

## 2.2.2. パーセンテージも表示するには？

ConfusionMatrixDisplayは、scikit-learnライブラリに含まれるクラスで、Confusion matrixを簡単に視覚化するための便利な方法だが、パーセンテージを表示する機能は備わっていない。

そこで、要素数から割合を計算し、その結果をConfusion Matrixに追加する。

~~~Python
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
import numpy as np

# 混同行列の生成
cm = confusion_matrix(y_val, y_pred)

# Confusion matrixの表示
disp = ConfusionMatrixDisplay(confusion_matrix=cm)
disp.plot(cmap=plt.cm.Blues)

# 描画された数値テキストを非表示にする。
# 下記コードを書いておかないとConfusionMatrixDisplay本来の数値が表示されてしまう。
for text in disp.ax_.texts:
    text.set_visible(False)

# 各区画に要素数とパーセンテージを表示（行ごとの合計に対する割合）
for (i, j), val in np.ndenumerate(cm): # 混同行列の各要素をインデックス（i, j）と値（val）として列挙
    row_sum = np.sum(cm[i, :])  # 混同行列の行iの合計を計算
    percentage = val / row_sum * 100 # 要素数を行の合計で割ってパーセンテージを計算
    color = 'white' if cm[i, j] > np.max(cm) / 2 else 'black' # 区画の値が最大値の半分を超える場合は白、そうでない場合は黒で文字を表示
    plt.text(j, i, f'{val}\n({percentage:.2f}%)', ha='center', va='center', color=color, fontsize=12) # 各区画に要素数とパーセンテージを表示。テキストを中央に配置し、フォントサイズは12に設定。

# X軸ラベル、Y軸ラベル、タイトルの追加
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix')

# Confusion matrixの表示
plt.show()
~~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3692239/1a12395c-bf0f-5b2c-6ba7-7c815c7502cf.png)

各要素数とパーセンテージを表示したConfusion matrixを作成することができた。