sammi@DataScience

Python, Machine Learning, Deep Leaning, Data Science, Kaggle.

スポンサーリンク

不均衡データの評価指標 - マシューズ相関係数(MCC)とF1スコアの比較

目次:

はじめに

前回は実装例に基づいて、ROC曲線が不均衡データに対して、Positiveは少数クラスの場合でも、Negativeは少数クラスの場合でも簡単に0.90+上がってしまうという欠点について説明してみました:

sammi-baba.hatenablog.com

というわけで、不均衡データ(imbalanced data)におけるモデル評価する時に、指標としてはマシューズ相関係数(Matthews Correlation Coefficient)とF1_Score使用した方がマシです。今回はMCCとF1_Scoreについて紹介し、さらに両者の違いを比較します。

MCCとF1_Scoreの紹介

F1_Scoreは分類モデルの評価指標の一つで、precisionとrecall両方とも考慮して、調和平均でスコアを計算します。ある程度precisionとrecallのバランスを表しています。スコアの範囲は最悪0~最善1まで。F1_Scoreの公式は下記の通り: f:id:sammi_baba:20190731170939j:plain

ちなみに、一般式としてFbeta_Scoreがあります:
f:id:sammi_baba:20190731170955j:plain

F1_Scoreはbeta=1の場合です。

同じく、F2_Score, F3_Score。。も存在しています。

betaというのは全公式の重みで、betaが大きければ、pecisionの重みが小さく、recallの重み大きくになります。

MCC真陽性(TP),偽陽性(FP),真陰性(TN),偽陰性(FN)を全部考慮したうえで、クラスのサイズが非常に異なっていても使用できる分類モデルの評価指標です。
本質的にというと、MCCは予測された二値分類結果と実際結果の相関係数です。つまり予測と答えはどれだけ近いか測るための尺度で、値の範囲は最悪-1~最善1まで。+1は完璧な予測結果、0はランダム予測結果、−1は予測結果と実際結果が完全な不一致を表しています。MCCの公式は下記の通り: f:id:sammi_baba:20190731171029j:plain

不均衡データにおけるMCCとF1_Scoreの実装

早速実装していきましょう~

今回はsklearnのmatthews_corrcoefを使用します。

必要なライブラリ:

import numpy as np
import matplotlib.pyplot as plt

from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

from sklearn.metrics import matthews_corrcoef
from sklearn.metrics import f1_score

①Positiveは少数クラスの場合

10000個の疑似データが約0 : 1 = 0.95 : 0.05の割合で生成されます(ノイズ含む):

X, y = make_classification(n_samples=10000, n_classes=2, weights=[0.95,0.05], random_state=42)
trainX, testX, trainy, testy = train_test_split(X, y, test_size=0.2, random_state=2)

LogisticRegressionで学習します:

model = LogisticRegression()
model.fit(trainX, trainy)
probs = model.predict_proba(testX)
probs = probs[:, 1] 

プロットします:

#plot
thresholds = np.linspace(0.1,1,num=10)
mcc_list = []
f1_list = []

for thr in thresholds:
    predict  = (probs > thr).astype(int)
    mcc = matthews_corrcoef(testy, predict)
    f1 = f1_score(testy, predict)
    mcc_list.append(mcc)
    f1_list.append(f1)
    
    
plt.plot(thresholds, f1_list, linestyle='--', label="f1_score")
plt.plot(thresholds, mcc_list, marker='.', label="mcc")
plt.legend()
plt.xlabel("Threshold")
plt.ylabel("Score")
plt.show()

プロットの結果:
f:id:sammi_baba:20190731171051j:plain

Positiveは少数クラスの場合には、MCCとF1_score両方とも適切にモデルを評価できます。

②Negativeは少数クラスの場合

10000個の疑似データが約0 : 1 = 0.05 : 0.95の割合で生成されます(ノイズ含む):

X, y = make_classification(n_samples=10000, n_classes=2, weights=[0.05,0.95], random_state=42)
trainX, testX, trainy, testy = train_test_split(X, y, test_size=0.2, random_state=2)

LogisticRegressionで学習します:

model = LogisticRegression()
model.fit(trainX, trainy)
probs = model.predict_proba(testX)
probs = probs[:, 1] 

プロットします:

#plot
thresholds = np.linspace(0.1,1,num=10)
mcc_list = []
f1_list = []

for thr in thresholds:
    predict  = (probs > thr).astype(int)
    mcc = matthews_corrcoef(testy, predict)
    f1 = f1_score(testy, predict)
    mcc_list.append(mcc)
    f1_list.append(f1)
    
    
plt.plot(thresholds, f1_list, linestyle='--', label="f1_score")
plt.plot(thresholds, mcc_list, marker='.', label="mcc")
plt.legend()
plt.xlabel("Threshold")
plt.ylabel("Score")
plt.show()

プロットの結果:
f:id:sammi_baba:20190731171106j:plain

Negativeは少数クラスの場合には、F1_scoreとMCCが似たような動きをしていないです。 なぜならば、F1_scoreは正負クラスの定義に影響されます。逆に、MCCは正負クラスをどう定義するかに依存せず、同じ動きを取ります。

まとめ

○ 不均衡データにおけるモデル評価指標としては、MCCとF1_scoreがおすすめです。
○ F1_scoreは正負クラスの定義に影響されやすい。
○ MCCは一番安全です。

スポンサーリンク