こんにちは、えびかずきです。
今回は他クラス分類モデルの評価と\(macroF_1\)スコアについて説明していきます。
最後におまけとしてscikit-learnでの実装方法も載せておきました。
こんな人におすすめ:
・他クラス分類のモデル評価方法を学びたい
・\(macroF_1\)の意味がよく分からないので教えて欲しい
最近機械学習のコンペに参加しているのですが、評価関数として\(macroF_1\)を使っているものがありました。
知らなかったので、良い機会だと思って記事にまとめておきます。
\(macroF_1\)は数式で表すと以下の通りですが、
\(\displaystyle macroF_1=\dfrac{1}{N}\sum_k^N {\dfrac{1}{1/precision_k+1/recall_k}}\)
これが何を意味するのか理解できるように説明していきたいと思います。
(もし誤り等あれば修正しますのでご連絡ください。)
それでは、順を追って解説していきましょう。
\(macroF_1\)スコアの意味
\(macroF_1\)は以下式で計算されるクラス分類モデルの評価指標です。
\(\displaystyle macroF_1=\dfrac{1}{N}\sum_k^N {\dfrac{1}{1/precision_k+1/recall_k}}\)
式中\(precision_k\)は適合度、\(recall_k\)は再現率を表す
\(precision_k = \dfrac{TP_k}{TP_k+FP_k}\)
\(recall_k = \dfrac{TP_k}{TP_k+FN_k}\)
\(TP,FP,FN\)はそれぞれ真陽性率,偽陽性率,偽陰性率を表す
式のとおりmacroF1スコアというのは、各クラスのF1スコアを平等に平均化した値となっています。
(F1スコアについては次のセクションで説明します。)
つまりクラスごとのデータ数の多少に関わらす、各クラスの分類性能を平等に評価する指標となっています。
要するに全体としての精度よりも、各クラスそれぞれの性能に重きを置いていると言うわけです。
抽象的な説明だと理解しづらいと思いますが、具体的な例で考えてみるとわかりやすいです。
macroF1スコアを使う具体例
具体的な例として野球のデータ分析を例に考えてみましょう。
たとえば、投手が投げるコースと、バッティングの結果について、その関係を調べることで試合に勝つための投球戦略を練るというケースを考えます。
分類モデルは、ボールのコースを説明変数として、バッティングの結果(アウト、1塁打、2塁打、3塁打、ホームラン)を分類します。
ちょっとでも野球をかじったことがあればわかると思いますが、当然この結果は『アウト』になる確率が最も高く、60~80%ほどに達するのが普通です。
しかしこの分析で重要なのは、どこに投げたらヒットを打たれてしまうかということであって、『アウト』以外の分類結果が非常に重要な意味を持ちます。
この場合単純なAccuracy(正確度)、つまり、[モデルが正しく分類できたデータ/全データ]だけの数字を見ていては、目的に即したモデルの性能評価ができません。
仮に以下の二つのモデルがあったとしましょう。
・①どこに投げても全てアウトと予測する雑魚モデル(accuracy=0.70)
・②ホームランが打たれる場所だけは精度よくわかるが他はランダムのモデル(accracy≒0.25)
→このモデルのaccuracyは1/5より少し良い数値になる筈
accuracyだけを見ると①のモデルの方が評価が高いですが、そもそもこのモデルの目的は打たれないように戦術を練ることですから、モデルとしては②の方が良いモデルであると評価される必要があります。
ここで、上の二つのモデルをmacroF1で比較するとどうなるでしょうか?
その結果は以下のようになるはずです。
・①どこに投げても全てアウトと予測する雑魚モデル(macroF1=0.16)
→アウトのクラスのみ値を持ちF1=0.82(recall=1,precision=0.7)である。macroF1はその1/5。
・②ホームランが打たれる場所だけは精度よくわかるが他はランダムのモデル(macroF1≒0.40)
→ホームランのクラスのみF1=1,その他はF1≒0.25とした。
このデータ分析の目的から考えると、macorF1で比較した方がまともそうですね。
さらに良いのは、アウト、1塁打、2塁打、3塁打、ホームランそれぞれの分類にゲームを左右する影響度として重みをつけて評価指標を作るというやり方です。
しかしながらそのような適切な重みを推定することは非常に難しいです。
よって今回のケースでmacroF1を使うというのは、それほど間違った選択ではないと言えます。
※なおこの野球の例は、prob.spaceのデータ分析コンペ「次の一投の行方を予測! プロ野球データ分析チャレンジ」から着想を得ました。
データ分析の内容は少し異なっています。
microF1スコアについて
macroF1があるのだから、当然”micro”F1スコアもあります。
microF1スコアは式で表すと以下のとおり。
\(\displaystyle microF_1=\dfrac{1}{\dfrac{1}{precision_{total}}+\dfrac{1}{recall_{total}}}\)
\(\displaystyle precision_{total} = \dfrac{\sum_k^N TP}{\sum_k^N TP+\sum_k^N FP}\)
\(precision_{total }= \dfrac{\sum_k^N TP}{\sum_k^N TP+\sum_k^N FN}\)
式のとおりmicroF1スコアは、各クラスのTP,FP,FNを合計してから、F1スコアを算出するという値です。
こちらの場合はクラス間のデータ偏りが結果に反映されます。
F1スコアの意味
\(F_1\)スコアはprecision(適合度)とrecall(再現度)の調和平均です。
\(\displaystyle F_1=\dfrac{1}{\dfrac{1}{precision_{total}}+\dfrac{1}{recall_{total}}}\)
precisionとrecallの算出には、以下で説明する混同行列について考える必要があります。
precision(適合度)とrecall(再現度)について
\(precision = \dfrac{TP}{TP+FP}\)
\(recall = \dfrac{TP}{TP+FN}\)
\(TP,FP,FN\)はそれぞれ真陽性率,偽陽性率,偽陰性率を表す
precisionとrecallの計算式は上の通りですが、TP,FP,FNの具体的な意味は、以下の表を見るとわかりやすいです。
たとえばある病気の診断を行うとします。
その診断は100%の精度があるわけではなくて、当然間違ってしまうケースが生じます。
このとき、病気の場合をP(陽性)、病気でない場合をN(陰性)、
予測が実際と合っている場合をT(真)、合っていない場合をF(偽)という記号で表したとき、結果は下表の4種類に分類されます。
ちなみにこれを混同行列といいます。
言葉でわかりやすいように説明すると、以下のようになります。
precision(適合度)=TP/(TP+FP):
陽性だと判断した予測全体のうち、それがどれだけ正確だったかを示す評価指標
recall(再現度)=TP/(TP+FN):
陽性だと判断すべきもののうち、それがどれだけ正確だったかを示す評価指標
多クラス分類の場合には、着目するクラス 対 その他のクラスの2クラス分類に当てはめて数値を算出します。
なぜprecision(適合度)とrecall(再現度)を考えるのか?
なぜprecision(適合度)とrecall(再現度)を考えるのかというと、accuracy(正確度)だけを考えていると、分布が偏っているケースの評価指標で不都合が出るためです。
たとえば以下のような、陰性と陽性の分布があったとして、これを真ん中の点線のラインで分類するモデルがあるとします。
このときのaccuracy(正確度)は、TNとTPの面積の和を二つの分布の総面積で割ったものとなります。
ここで、分布が偏っているケースを考えましょう。
以下のように陽性が圧倒的に少なくて、陰性が多いというケースで考えます。
このときもaccuracy(正確度)は、上のケースと同様にTNとTPの面積の和を二つの分布の総面積で割ったものとなりますが、TNの成分が大きすぎて陽性の方の分類性能が隠れてしまいます。
ということで、こういうデータが偏っているケースにおいては、着目するクラス単体のデータで性能評価をした方が良いです。
したがってこのようなケースで、precisionとrecallが登場するというわけです。
なぜ\(F_1\)スコアの調和平均を取るのか
F1の算出に使うprecision(適合度)、recall(再現度)は分子がいずれもTPで同じです。異なるのは分母のFPとFNの部分なので、分母の部分で算術平均をとるのが自然、すなわちそれは結果的にprecisionとrecallの調和平均をとるということになる。
という説明が以下のstackoverflowの記事に投稿されていて、なるほどなあと思った。
多分その通りなんだと思います。
他にも、低い数値に罰則を与えたいからというような説明もWeb上でちらほら見かけたが、あまりしっくりこなかった。
\(F_β\)スコアというのもある
ちなみに\(F_β\)スコアというのもあって、こちらは目的に合わせてprecisionとrecallに重みを付けます。
おまけ:scikit-learnによる実装
scikit-learnによるmacroF1算出の方法について簡単に載せておきます。
方法はいくつかありますが、ここでは交差確認をする場合のスコア指定を変更する例について載せておきます。
以下のようにcross_val_scoreのscoreingに”f1-macro”を指定すればOKです。
#RandomForest(n=100)/交差確認
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
import numpy as np
forest = RandomForestClassifier(n_estimators=100, random_state=0)
scores = cross_val_score(forest, X, y, cv = 5, scoring="f1_macro")
まとめ
今回は他クラス分類モデルの評価と\(macroF_1\)スコアについて説明しました。
ぱっと見複雑そうな式をしていますが、中身を詳しくみてみると意外と単純です。
まとめると、macroF1スコアは多クラス分類のモデル評価に使う指標で、各クラスのF1スコアの平均を取ったものです。
そして、「データの偏りに関わらずどのクラスの性能も同じくらい大事!」という場面で使います。
これでmacroF1に出くわしても戸惑うことは無くなりましたね。
参考
参考URL
以下はstack overflowの記事。調和平均を取る意味について書いてあります。
参考書籍
実装方法だけでなく、F1スコアの意味についても説明があったので参考になりました。
コメントを書く