静かなる名辞

pythonとプログラミングのこと

2019/03/22:TechAcademyがteratailの質問・回答を盗用していた件
2019/03/26:TechAcademy盗用事件 公式発表と深まる疑念


【python】sklearn 0.20でclassification_reportの仕様が変わっていた

はじめに

 遅まきながら、sklearn 0.20でclassification_reportの仕様が変わったことに気づきました。

 基本的な使い方は変わりませんが、それなりに大きな変化になります。

変更点

 まず0.19の引数と出力のフォーマット。

sklearn.metrics.classification_report(y_true, y_pred,
    labels=None, target_names=None, 
    sample_weight=None, digits=2)
>>> print(classification_report(y_true, y_pred, target_names=target_names))
             precision    recall  f1-score   support

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

avg / total       0.70      0.60      0.61         5

sklearn.metrics.classification_report — scikit-learn 0.19.2 documentation

 個人的に使い慣れていたのはこちらです。

 次に0.20の引数と出力のフォーマット。

sklearn.metrics.classification_report(y_true, y_pred, 
    labels=None, target_names=None, 
    sample_weight=None, digits=2, output_dict=False)
>>> print(classification_report(y_true, y_pred, target_names=target_names))
              precision    recall  f1-score   support

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

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

sklearn.metrics.classification_report — scikit-learn 0.20.4 documentation

 変わっていますね。まず、output_dictという引数が追加されています。使い方は容易に想像がつき、ドキュメントにも説明がある通りですが辞書を返してくれるようになります。

 また、全体の結果のとりまとめのところでマイクロ平均、マクロ平均、重み付き平均を返してくれるようになりました。これらの意味については以前記事にしたので、そちらを見てください。

【python】分類タスクの評価指標の解説とsklearnでの計算方法 - 静かなる名辞

output_dictを試す

 大きな変更点はここなので、試してみましょう。ドキュメントと同様の例で打ち込んでいます。

>>> from sklearn.metrics import classification_report
>>> d = classification_report([0,1,2,2,2], [0,0,2,2,1],
...         target_names = ['class 0', 'class 1', 'class 2'],
...         output_dict=True)
>>> 
>>> from pprint import pprint
>>> pprint(d)
{'class 0': {'f1-score': 0.6666666666666666,
             'precision': 0.5,
             'recall': 1.0,
             'support': 1},
 'class 1': {'f1-score': 0.0, 'precision': 0.0, 'recall': 0.0, 'support': 1},
 'class 2': {'f1-score': 0.8,
             'precision': 1.0,
             'recall': 0.6666666666666666,
             'support': 3},
 'macro avg': {'f1-score': 0.48888888888888893,
               'precision': 0.5,
               'recall': 0.5555555555555555,
               'support': 5},
 'micro avg': {'f1-score': 0.6, 'precision': 0.6, 'recall': 0.6, 'support': 5},
 'weighted avg': {'f1-score': 0.6133333333333334,
                  'precision': 0.7,
                  'recall': 0.6,
                  'support': 5}}

 これはpandasデータフレームに変換できます。

>>> import pandas as pd
>>> df = pd.DataFrame(d)
>>> df
            class 0  class 1   class 2  macro avg  micro avg  weighted avg
f1-score   0.666667      0.0  0.800000   0.488889        0.6      0.613333
precision  0.500000      0.0  1.000000   0.500000        0.6      0.700000
recall     1.000000      0.0  0.666667   0.555556        0.6      0.600000
support    1.000000      1.0  3.000000   5.000000        5.0      5.000000

 なのでデータフレームを介して記録しておきパラメータチューニングに使うとか、TeXの表やビジュアル的なグラフなど任意のフォーマットに吐き出すといった処理が行いやすくなっています。

まとめ

 気づくのが遅れましたが、健全な方向に改良されたと思います。使いやすくなった反面、これで済むようになると他のsklearn.metricsの関数を叩かなくなるので、使い方を忘れるかも・・・という懸念があります(笑)。