読者です 読者をやめる 読者になる 読者になる

人間だったら考えて

考えて考えて人間だったら考えて

不均衡データに対する予測結果のAccuracyは簡単に上がってしまう

機械学習 統計学

この記事は何?

機械学習における不均衡データの扱いは,学習時にも評価時にも注意する必要があります.
例えばSVMにおける学習では,クラス重みを事前に設定することで,不均衡データによるバイアスを軽減できます.
不均衡データに対する予測精度の評価について,Accuracyを用いて評価を行うと,不当に高い値が得られてしまいます.
この記事では不均衡データに対する予測結果をどのように評価すべきかについて紹介します.

不均衡データにおけるAccuracy評価を簡単に上げる

Accuracyは次式で定義されます.
 {\rm Accuracy}=\frac{{\rm TP}+{\rm TN}}{{\rm TP}+{\rm TN}+{\rm FP}+{\rm FN}}

ここで,正例数 n_{+}が負例数 n_{-}よりも多い不均衡データを考えます.
この不均衡データに対して全て正例と予測します.
すると,{\rm Accuracy}=\frac{n_{+} + 0}{n_{+} + 0 + n_{-} +0}=\frac{n_{+}}{n_{+}+n_{-}}となります.
 n_{+} \gg n_{-}より,Accuracyは1に近づいていきます.

実際に実験してみます.正例/負例の比率を0.5,0.99として,それぞれの予測結果におけるAccuracyを求めます.

import numpy as np
from sklearn.metrics import accuracy_score, confusion_matrix
def make_labels(N, positive_ratio=0.5):
    n_positive = int(N * positive_ratio)
    n_negative = N - n_positive
    labels = np.r_[np.ones(n_positive), np.zeros(n_negative)]
    return labels
N = 1000
positive_ratio = 0.5
y_true = make_labels(N, positive_ratio=positive_ratio)
y_pred = np.ones(N)
print("Accuracy:", accuracy_score(y_true, y_pred))
    Accuracy: 0.5
positive_ratio = 0.99
y_true = make_labels(N, positive_ratio=positive_ratio)
y_pred = np.ones(N)
print("Accuracy:", accuracy_score(y_true, y_pred))
    Accuracy: 0.99

というわけで,不均衡データでは簡単に高いAccuracyを出すことができます.
逆に言うと,Accuracyだけ見てすごい!と言うのは危険だということです.
Accuracyの評価の際には,ラベルの分布も一緒に見てすごいかどうか考えた方が良さそうです.

じゃあどうしたらいいの?

不均衡データに対する予測結果の評価において,Matthews correlation coefficient (MCC)が用いられています.
MCCは次式で定義されます.
 \frac{{\rm TP}\times {\rm TN} - {\rm FP} \times {\rm FN}}{\sqrt{ ({\rm TP}+{\rm FP}) ({\rm TP}+{\rm FN}) ({\rm TN}+{\rm FP}) ({\rm TN} + {\rm FN})}}
MCCは-1から1の値を取り,正しい予測のときに1・逆の予測のときに-1・ランダム予測のときに0となります.
正例に関する予測精度と負例に関する予測精度が共に考慮されているため,不均衡データに対する予測精度の評価に使えるということ…でしょうか.
MCCを使って先程の実験を行います.

positive_ratio = 0.5
y_true = make_labels(N, positive_ratio=positive_ratio)
y_pred = np.ones(N)
print(matthews_corrcoef(y_true, y_pred))
    0.0
positive_ratio = 0.99
y_true = make_labels(N, positive_ratio=positive_ratio)
y_pred = np.ones(N)
print(matthews_corrcoef(y_true, y_pred))
    0.0

 {\rm TN}=0かつ{\rm FN}=0なので,MCCは0となりました.

その他

評価指標はそれぞれ一長一短で特性も異なるので,出来る限り複数種類の評価指標で予測精度を検証した方が良いです.
もちろん,目的に応じた評価指標を使うべきなのですが…