- 例えば、真の値 [1, 1, 0, 0] があるとする。(0: 陰, 1: 陽)
- ある予測器にかけたスコアが [0.9, 0.4, 0.6, 0.1] だとする。値が大きいほど 1 の可能性が高い。
- この場合 0.6 と 0.4 の部分の予測は自信が無く、実際間違っている。
これを sklearn でプロットしてみる。ここで
- FPR: 偽陽性率。0 に近いほど間違って偽と判定してしまった割合が減って良い。分母は実際に偽だった数。
- TPR: 真陽性率。1 に近いほど正しく真と判定した割合が増えて良い。分母は実際に真だった物。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.metrics import roc_curve
y = np.array([1, 1, 0, 0])
scores = np.array([0.9, 0.4, 0.6, 0.1])
fpr, tpr, thresholds = roc_curve(y, scores)
print(f'FPR: {fpr}, TPR: {tpr}, thresholds: {thresholds}')
print(f'AUC: {auc(fpr, tpr)}')
display(pd.DataFrame({'fpr': fpr, 'tpr': tpr, 'thresholds': thresholds}))
plt.plot(fpr, tpr)
FPR: [0. 0. 0.5 0.5 1. ], TPR: [0. 0.5 0.5 1. 1. ], thresholds: [1.9 0.9 0.6 0.4 0.1]
AUC: 0.75
fpr | tpr | thresholds | |
---|---|---|---|
0 | 0.0 | 0.0 | 1.9 |
1 | 0.0 | 0.5 | 0.9 |
2 | 0.5 | 0.5 | 0.6 |
3 | 0.5 | 1.0 | 0.4 |
4 | 1.0 | 1.0 | 0.1 |
- 閾値が 1.9 だと全部 0 になってしまうので FPR も TPR も 0。
- 閾値を 0.9 にするとスコア 0.9 のやつだけが 1 と判定される。FPR は 0 のままだが TPR は 0.5 に上がる。
- 閾値を 0.6 にするとスコア 0.6 以上が 1 と判定される。3つ目の値が 1 と誤判定されるので FPR は 0.5 に上がる。TPR は 5 のまま。
- 閾値を 0.4 にすると。。。
というふうに FPR を低く保ったまま TPR を上げるのが難しいのが良くわかるグラフが出来上がる。より良い予測器はグラフの左下部分の面積が広い。その面積を AUC と呼び、予測器の評価に使う。
参考:
個人的意見では FPR の定義が TPR と対称的で無いのが気に食わない。例えば TNR = 1 - FPR = TN / TN + FP として、TNR と TPR でグラフを描いた方が「TNR と TPR の両方同時に 1 に近いほうが良い」となって分かりやすいと思うのだが、決まっている物は仕方がない。