#先に結論
F1-Scoreは「少数ラベル評価」ではなく「Positiveサンプル評価」であり、positiveラベルが少数である時のみ、少数ラベルを評価できる。
negativeラベルが少数であるときや、positiveとnegativeのどちらが少数か不明な場合では期待する動きをしない可能性があるので気を付けましょう
#コードで見てみよう
from sklearn.metrics import f1_score, accuracy_score
import numpy as np
# 990件のnegativeと10件のpositive
y_true = np.zeros(1000)
y_true[:10] = 1
y_pred = np.zeros(1000)
y_pred[5:15] = 1
print(accuracy_score(y_true, y_pred))
# 0.99
print(f1_score(y_true, y_pred))
# 0.5
# 990件のpositiveと10件のnegative
y_true = np.ones(1000)
y_true[:10] = 0
y_pred = np.ones(1000)
y_pred[5:15] = 0
print(accuracy_score(y_true, y_pred))
# 0.99
print(f1_score(y_true, y_pred))
# 0.9949494949494949
見てわかる通り、positiveが多数ラベルの際にはF1はほぼAccuracyと同じ値になる。
#簡単な理由
F1スコアは以下の式で計算される。
\begin{align}
F1 = \frac{2 \times Recall \times Precision}{Recall + Precision} \\
Recall = \frac{TP}{TP + FN} \\
Precision = \frac{TP}{TP + FP}
\end{align}
直観的に行くため、ここでTPやFNにどういった数字が入っているかを考える。
pos(GT) | neg(GT) | |
---|---|---|
pos(予測) | TP | FP |
neg(予測) | FN | TN |
ここで、positive >> negativeにおいてはおよそTP >> FN, FP > TNとなる。まずpos(GT)が圧倒的に大きいのでTP+FN(positiveサンプルの総量)が大きな値に。不均衡的にpositiveサンプルの多くはTPに。一部がFNになる。また、pos(予測)のうちでも多くがTPになるが、一部がFPになる。そうなると、RecallやPrecisionは
Recall = \frac{1}{1 + \frac{FN}{TP}} , (TP >> FNとすると\frac{FN}{TP}⇒0.000に近くなるため) \\
=\frac{1}{1+0.000} = 0.999...
結局RecallやPrecisionはTPがどれだけできているかを見ているので、positiveサンプルがどれだけ正解できているかを見ているのであって、少数ラベルの出来具合をみているわけではないんですよね。
もちろん、positiveサンプルが少数の場合は、少数ラベルの評価指標にもなりえますが、そこをすっ飛ばしてとりあえずラベルの偏りがあるからF1scoreみたいにするのは良くないと思います。では