機械学習のクラス分類モデルを評価する際に用いる混同行列を簡単に表示できるちょっとしたライブラリがあったので紹介します。
混同行列とは、機械学習で予測したクラス分類の結果をまとめた行列です。ちょうど上の画像のように「どのクラスに分類されて」「実際はどのクラスだったか」がひと目でわかる表のことですね。
課題
scikit-learnにも混同行列を表示する関数があるのですが、ラベル情報が含まれていないので、例えば第三者に結果を報告する際には、わかりやすく加工することが必要でした。
from sklearn.metrics import confusion_matrix y_true = ["cat", "ant", "cat", "cat", "ant", "bird"] y_pred = ["ant", "ant", "cat", "cat", "ant", "cat"] print(confusion_matrix(y_true, y_pred)) # [[2 0 0] # [0 0 1] # [1 0 2]]
そのため、整形するために独自に関数を作っている方もQiitaで見つけました。
この問題を解決するのがpycmです。
pycm
pycmは混同行列の取扱いをサポートするライブラリです。用途がはっきりしていてわかりやすいかと思います。
例えば今scikit-learnで表示した混同行列はpycmだと下記のように表示することができます。
from pycm import ConfusionMatrix y_true = ["cat", "ant", "cat", "cat", "ant", "bird"] y_pred = ["ant", "ant", "cat", "cat", "ant", "cat"] cm = ConfusionMatrix(actual_vector=y_true, predict_vector=y_pred) cm.print_matrix() # Predict ant bird cat # Actual # ant 2 0 0 # # bird 0 0 1 # # cat 1 0 2
ラベル付きで表示することができました。 ちょっとしたライブラリなんですが、こういうものが意外と重宝するんですよね。
その他の機能も
ただ表示するだけでは終わりません。その他にも便利な機能もあるので紹介します。
混同行列の正規化
cm.print_normalized_matrix() # Predict 0 1 2 # Actual # 0 0.9661 0.0339 0.0 # # 1 0.0 0.97183 0.02817 # # 2 0.0 0.02083 0.97917
「1 vs それ以外」の表示
cm.print_matrix(one_vs_all=True, class_name=0) # Predict 0 ~ # Actual # 0 57 2 # # ~ 0 119
辞書型への変換
cm.table # {0: {0: 57, 1: 2, 2: 0}, 1: {0: 0, 1: 69, 2: 2}, 2: {0: 0, 1: 1, 2: 47}}
数値とラベルのマッピング
cm.relabel(mapping: dict)
を使うことで簡単にクラスの名前にもマッピングすることができます。
y_true = [0, 0, 1, 0, 2, 2, 1, 0, 0, 1, 2, 1] y_pred = [1, 0, 1, 2, 2, 2, 1, 1, 2, 2, 0, 1] cm = ConfusionMatrix(actual_vector=y_true, predict_vector=y_pred) cm.print_matrix() # Predict 0 1 2 # Actual # 0 1 2 2 # # 1 0 3 1 # # 2 1 0 2 mapping = {0: "クラス1", 1: "クラス2", 2: "クラス3"} cm.relabel(mapping=mapping) # マッピング cm.print_matrix() # Predict クラス1 クラス2 クラス3 # Actual # クラス1 1 2 2 # # クラス2 0 3 1 # # クラス3 1 0 2
マッピングしたあとに cm.table
を呼び出すと前述したQiitaの記事と同じことができます。
import pandas as pd pd.DataFrame(cm.table)
混同行列同士の比較も
またもう1つ便利な機能として、「混同行列同士の比較」があります。 ここでは、「ロジスティクス回帰とSVMで分類結果を比較する」というユースケースを例として考えてみましょう。
from sklearn.linear_model import LogisticRegression from sklearn.svm import SVC lr = LogisticRegression() lr.fit(X_train, y_train) y_lr_pred = lr.predict(X_test) svc = SVC() svc.fit(X_train, y_train) y_svc_pred = svc.predict(X_test) y_true = y_test
この分類結果を混同行列として次のように簡単に比較することができます。
Compare
クラスを使います。
from pycm import Compare cm_lr = ConfusionMatrix(actual_vector=y_true, predict_vector=y_lr_pred) cm_svc = ConfusionMatrix(actual_vector=y_true, predict_vector=y_svc_pred) cp = Compare({"lr": cm_lr,"svc": cm_svc}) print(cp) # Best :lr # # Rank Name Class-Score Overall-Score # 1 lr 3.0 4.0 # 2 svc 0.6 1.11667
今回の例ではロジスティク回帰の方が良い結果だったようです。
さいごに
混同行列を表示するのに便利な「pycm」を紹介しました。汎用的というわけではありませんが、かゆいところに手が届く孫の手的なライブラリですね。こういう日常に転がっている問題に気づけるようになりたいと常々思っています。
今回使ったコードはすべてGitHubにあげてあります。