nikkie-ftnextの日記

イベントレポートや読書メモを発信

scikit-learnでprecision, recall, f1_scoreを一度に求められる! sklearn.metrics.precision_recall_fscore_support

はじめに

一射絶命、nikkieです。
ツルネを見終えました(沙絵ちゃんかわいい

scikit-learnの実装を眺めていて、「各種評価指標を一発で出せる関数あるじゃん!」と気付きました。
この感動を共有していきます。

目次

sklearn.metrics.precision_recall_fscore_support

Compute precision, recall, F-measure and support for each class.

  • F-measureですが、要はF1スコアです
    • F1スコアは実はF-betaスコアのbeta=1のケースです。precision_recall_fscore_support関数にはbeta引数があり、デフォルト値は1.0です
  • supportとは、y_trueの中で各クラスに属するサンプルの数です1

4要素のタプルを返します。
(precision, recall, f1_score, support)

Re: scikit-learnのf1_scoreのaverage引数に指定するmicroやmacroやsamplesって、なに?

average引数を使いこなすための素振り記事の内容は、precision_recall_fscore_supportを使うと一瞬でした!

今回の動作環境

  • Python 3.11.4
  • scikit-learn 1.3.0
joblib==1.3.1
numpy==1.25.1
scikit-learn==1.3.0
scipy==1.11.1
threadpoolctl==3.2.0

指標算出の前準備

MultiLabelBinarizerで処理した後のラベルを扱っていきます。

>>> import numpy as np
>>> from sklearn.metrics import precision_recall_fscore_support
>>> y_true = np.array([[1,1,0], [1,0,0], [1,1,1], [0,1,1], [0,0,1]])
>>> y_pred = np.array([[1,0,1], [0,1,0], [1,0,1], [0,0,1], [0,0,1]])

クラスごとに算出(average=None

average引数のデフォルト値はNoneで、クラスごとに各指標を算出します。

>>> precision_recall_fscore_support(y_true, y_pred)
(array([1.  , 0.  , 0.75]), array([0.66666667, 0.        , 1.        ]), array([0.8       , 0.        , 0.85714286]), array([3, 3, 3]))

3つのクラスについてインデックス+1で表すと

  • クラス1
    • precision 1
    • recall 0.66666667
    • F1 score 0.8
  • クラス2
    • precision 0
    • recall 0
    • F1 score 0
  • クラス3
    • precision 0.75
    • recall 1
    • F1 score 0.85714286

クラスごとの混同行列を書いて確認した結果と一致します。
一発で求まるなんて!

サンプルごとに算出(転置してaverage=None

y_truey_predを両方転置して、average引数にNoneを指定したらサンプルごとに算出できます。

>>> precision_recall_fscore_support(y_true.T, y_pred.T)
(array([0.5, 0. , 1. , 1. , 1. ]), array([0.5       , 0.        , 0.66666667, 0.5       , 1.        ]), array([0.5       , 0.        , 0.8       , 0.66666667, 1.        ]), array([2, 1, 3, 2, 1]))

5つのサンプルについてインデックス+1で表すと

  • サンプル1
    • precision 0.5
    • recall 0.5
    • F1 score 0.5
  • サンプル2
    • precision 0
    • recall 0
    • F1 score 0
  • サンプル3
    • precision 1
    • recall 0.66666667
    • F1 score 0.8
  • サンプル4
    • precision 1
    • recall 0.5
    • F1 score 0.66666667
  • サンプル5
    • precision 1
    • recall 1
    • F1 score 1

サンプルごとの混同行列を書いて確認した結果と一致しますね!

average="micro"

>>> precision_recall_fscore_support(y_true, y_pred, average="micro")
(0.7142857142857143, 0.5555555555555556, 0.6250000000000001, None)

average引数の値がNoneでないとき、supportはNoneになります2

average="macro"

>>> precision_recall_fscore_support(y_true, y_pred, average="macro")
(0.5833333333333334, 0.5555555555555555, 0.5523809523809523, None)

average="samples"

>>> precision_recall_fscore_support(y_true, y_pred, average="samples")
(0.7, 0.5333333333333333, 0.5933333333333334, None)

終わりに

sklearn.metrics.precision_recall_fscore_supportでprecision, recall, f1_scoreの3つを一度に求められることを共有しました。

  • y_truey_predからタプル(precision, recall, f1_score, support)を得られます
  • average引数を変えて、precision, recall, f1_scoreを一通り求められます

scikit-learnを初めて触るときはtoo muchな印象ですが、慣れてきた今となっては初手でprecision_recall_fscore_supportを使いたいなと思いました。コスパ最高じゃん!
なお、各種評価指標については『評価指標入門』がオススメです3。私も勉強中〜

P.S. zero_division引数もあります

zero_division引数はF1 scoreに限らず、precisionにもrecallにも提供されます。
これらを一発で出せるprecision_recall_fscore_supportzero_division引数を持ちます!

P.S. その2 各種評価指標はprecision_recall_fscore_supportを呼び出す実装です!

なお、precision_recall_fscore_supportの返り値のうち使わない評価指標は_を並べたアンパック代入で受けることで捨てています。


  1. The support is the number of occurrences of each class in y_true.(ドキュメントより)
  2. support None (if average is not None)(ドキュメントより)