【sklearn】Classification_reportの使い方を丁寧に

はじめに

本記事ではsklearn.metrics.classification_reportについて丁寧に説明します.

公式ドキュメント:

scikit-learn.org

classification_reportの役割

classification_reportは,正解ラベル列と予測ラベル列を入力すると,適合率(precision),再現率(recall),F1スコア,正解率(accuracy),マクロ平均,マイクロ平均を算出してくれる優れものです.

分類タスクの評価に有効で,二値分類だけでなく,マルチクラス分類の評価も可能です.

classification_reportの入出力

  • 入力

 2つの一次元リストです.1つめが正解ラベル列,2つめがモデルの予測ラベル列です.

例:[0, 1, 1, 0]['pos', 'neg', 'neg', 'pos']など

  • 出力

文字列です.各評価値が良い感じに表示されるようなフォーマットになっています.

classification_reportの宣言

特に宣言は必要なくて,モジュールをインポートするだけです.

from sklearn.metrics import classification_report

出力の説明

入力は公式ドキュメントのものを借りてくるとします.入力のリストの要素は0~2なので,3値分類だと考えることができます.

from sklearn.metrics import classification_report
y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
print(classification_report(y_true, y_pred))

出力は以下のようになります.

              precision    recall  f1-score   support

           0       0.50      1.00      0.67         1
           1       0.00      0.00      0.00         1
           2       1.00      0.67      0.80         3

    accuracy                           0.60         5
   macro avg       0.50      0.56      0.49         5
weighted avg       0.70      0.60      0.61         5

出力は表になっていて,各ラベルに対する評価値を確認できます.基本的に横向きに見ればよくて,例えば0の行を見ると,ラベル0のprecisionは0.5で,recallは1.00でーということが分かります.

列ラベルの説明

  • precision

適合率です.モデルが真と予測した数を分母,その中で実際に正解した数を分子にした値です.

 precision = \frac{TP}{TP+FP}

  • recall

再現率です.正解データ中の真の数を分母,その中でモデルが正解した数を分子にした値です.

 recall = \frac{TP}{TP+FN}

  • f1-score

F値です.precisionとrecallの調和平均です.

 f_{1}score = \frac{2\times precision \times recall}{precision + recall}

  • support

正解データに含まれている個数です.

行ラベルの説明

  • 0,1,2

ラベルそのものです.入力によってここは変化します.

  • accuracy

正解率です.事例数を分母,その中でモデルが正解した数を分子にした時の値です.

 accuracy = \frac{TP+TN}{TP+FP+TN+FN}

マクロ平均です.各ラベルの評価値を合計して,単にラベルの種類数で割って平均を取ります.例えば,ラベル0,1,2のprecisionを P_0, P_1, P_2とすると,precisionのマクロ平均は

 \frac{P_0 + P_1 + P_2}{3}

で求められます.

重み付き平均です.各ラベルの評価値とそのラベル数(=support)の積を合計して,事例数で割ります.例えば,ラベル0,1,2のprecisionを P_0, P_1, P_2,ラベルの個数を n_0, n_1, n_2とすると,precisionの重み付き平均は

 \frac{P_0n_0 + P_1n_1 + P_2n_2}{n_0+n_1+n_2}

で求められます.

オプション

target_names=

ラベル名を指定できます.普通,機械学習にかけるときには,正解ラベルはIDに変換されていると思うので,それを元に戻すようなことができます.target_names=には一次元リストを与えます.IDを添字とみなして,その要素に置き変える形です.

from sklearn.metrics import classification_report

y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
names = ['positive', 'negative', 'neutral']
print(classification_report(y_true, y_pred, target_names=names))
'''
              precision    recall  f1-score   support

    positive       0.50      1.00      0.67         1
    negative       0.00      0.00      0.00         1
     neutral       1.00      0.67      0.80         3
以下略
'''

labels=

どのラベルを評価するか指定できます.デフォルトでは,正解データに存在する全てのラベルが評価されますが,評価するラベルを制限したい場合や,正解データに含まれないが本当は存在するラベルを仮定して評価する際に有効です.labels=に評価したいラベルの一次元リストを与えることで評価値を算出できます.

from sklearn.metrics import classification_report

y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
print(classification_report(y_true, y_pred, labels=[0,1,2,3]))
'''
              precision    recall  f1-score   support

           0       0.50      1.00      0.67         1
           1       0.00      0.00      0.00         1
           2       1.00      0.67      0.80         3
           3       0.00      0.00      0.00         0
以下略
'''

正解データに含まれないラベル3もあることを明示的に指定できており,評価値も出力されています.

sample_weight=

各事例(サンプル)に対する重みを指定できます.ラベルに対する重みではないことに注意してください.sample_weight=に重みを並べた一次元リストを与えます.

以下の例では,先頭のデータの重みは1で,それ以外のデータの重みは0としているため,結局,先頭要素の評価だけが全体の評価に影響します.

from sklearn.metrics import classification_report

y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
weight = [1, 0, 0, 0, 0]
print(classification_report(y_true, y_pred, sample_weight=weight))
'''
              precision    recall  f1-score   support

           0       1.00      1.00      1.00       1.0
           1       0.00      0.00      0.00       0.0
           2       0.00      0.00      0.00       0.0

    accuracy                           1.00       1.0
   macro avg       0.33      0.33      0.33       1.0
weighted avg       1.00      1.00      1.00       1.0
'''

digits=

小数点以下を何桁まで表示するかを整数で指定できます.デフォルトは2です.

from sklearn.metrics import classification_report

y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
print(classification_report(y_true, y_pred, digits=4))
'''
              precision    recall  f1-score   support

           0     0.5000    1.0000    0.6667         1
           1     0.0000    0.0000    0.0000         1
           2     1.0000    0.6667    0.8000         3

    accuracy                         0.6000         5
   macro avg     0.5000    0.5556    0.4889         5
weighted avg     0.7000    0.6000    0.6133         5
'''

output_dict=

評価値を辞書で返します.このオプションはbool値です.デフォルトはFalseになっているため,結果は文字列で得られます.単に評価値を目視するだけなら文字列でも構いませんが,その先も評価値を用いて何かするプログラムが続いている場合,直接評価値を参照できたほうが便利です.

返り値の辞書は,辞書名[行名][列名]という形で参照できます.

from sklearn.metrics import classification_report

y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
eval_dict = classification_report(y_true, y_pred, output_dict=True)
print(eval_dict['0']['precision']) # 0.5
print(eval_dict['macro avg']['f1-score']) # 0.48888888888888893

micro avgが表示される条件

micro avgはマイクロ平均です.

色々入力を変えていると,出力にmicro avgが出力される時とaccuracyが表示されることがあります.

micro avgが表示されるときは,

  1. オプションとしてlabels=が指定されていること

  2. 正解・推定データに含まれるラベル種類と,labels=で指定したラベル種類が不一致

の2つの条件を同時に満たすときです.どちらか一方でも満たさない場合,accuracyが表示されます.

というのは,条件を満たさない場合は,f1スコアのマイクロ平均と正解率が一致します.このことから,micro avgを計算する必要はなく,単にaccuracyが表示されます.

from sklearn.metrics import classification_report
# 0,1,2が全て含まれている入力
y_true = [0, 1, 2, 2, 2]
y_pred = [0, 0, 2, 2, 1]
print(classification_report(y_true, y_pred, labels=[0,1,2]))
'''
(中略)
    accuracy                           0.60         5
   macro avg       0.50      0.56      0.49         5
weighted avg       0.70      0.60      0.61         5
'''
# accuracyが表示される

一方で,2.の条件を満たす場合は,f1スコアのマイクロ平均と正解率は一致しません.よって,micro avgを得るためには真面目に計算するしかなく,micro avgが表示されます.

from sklearn.metrics import classification_report
# ラベル1が含まれていない入力
y_true = [0, 0, 2, 2, 2]
y_pred = [0, 0, 2, 2, 0]
print(classification_report(y_true, y_pred, labels=[0,1,2]))
'''
(中略)
   micro avg       0.80      0.80      0.80         5
   macro avg       0.56      0.56      0.53         5
weighted avg       0.87      0.80      0.80         5

'''
# micro avgが表示される