上一篇博客介绍了 PR 曲线,这一篇博客介绍另一种曲线 ROC 曲线。
ROC曲线
ROC(Receiver Operating Characteristic Curve),它其实是统计学上经常使用的一个术语,它描述的是 TPR 和 FPR 之间的关系。
那么我们首先来看看 TPR 和 FPR 这两个指标是什么意思?
TRP,是 True Positive Result 的缩写。其实 TPR 和我们之前学的 R e c a l l Recall Recall 是一个意思。
FPR 是 False Positive Result 的缩写。其实它和 TPR 是对应的关系。
其实 TPR 和 PPR 之前也存在着一种联系。我们还是画出一条 score 轴,轴上分布着很多样本点,而星形是我们关注的样本点,即分类为 1,那么圆形的分类为 0。
当我们取不同的 t h r e s h o l e threshole threshole(阈值)来对我们的样本进行分类的时候,相应的 TPR 和 FRP 是怎样变化的?
当我们的 t h r e s h o l e threshole threshole 取得非常大的时候,我们计算相应的 TPR 和 PPR 。
如果我们减小
t
h
r
e
s
h
o
l
e
threshole
threshole ,计算相应的 TPR 和 PPR 。
我们继续减少 t h r e s h o l e threshole threshole ,计算相应的 TPR 和 PPR 。
那么很容易观察到,随着
t
h
r
e
s
h
o
l
e
threshole
threshole 的变化,我们的 TPR 和 PPR 是怎么变化的。在
t
h
r
e
s
h
o
l
e
threshole
threshole 逐渐降低的过程中,FPR 是在逐渐升高的,TPR 也在逐渐升高。换句话说,TPR 和 PPR 之间是呈现相一致的趋势。TPR 越高,FPR 跟着也变高。和
p
r
e
c
i
s
i
o
n
precision
precision 和
r
e
c
a
l
l
recall
recall 之间的关系是正好相反的。
当然,我们也可以直观地理解一下,为了提高 TPR,我们就必须拉低阈值,阈值拉低以后,相应的我们犯 FP 这种错误也会增高。其实 ROC 曲线就是刻画这两个指标之间的关系。
下面我们实现一个 TPR 和 FPR 两个函数。我们在之前的 metrics.py
文件中添加下列函数。
# metrics.py
def TN(y_true, y_predict):
assert len(y_true) == len(y_predict)
return np.sum((y_true == 0) & (y_predict == 0))
def FP(y_true, y_predict):
assert len(y_true) == len(y_predict)
return np.sum((y_true == 0) & (y_predict == 1))
def FN(y_true, y_predict):
assert len(y_true) == len(y_predict)
return np.sum((y_true == 1) & (y_predict == 0))
def TP(y_true, y_predict):
assert len(y_true) == len(y_predict)
return np.sum((y_true == 1) & (y_predict == 1))
# 混淆矩阵
def confusion_matrix(y_true, y_predict):
return np.array([
[TN(y_true, y_predict), FP(y_true, y_predict)],
[FN(y_true, y_predict), TP(y_true, y_predict)]
])
# 精准率
def precision_score(y_true, y_predict):
assert len(y_true) == len(y_predict)
tp = TP(y_true, y_predict)
fp = FP(y_true, y_predict)
try:
return tp / (tp + fp)
except:
return 0.0
# 召回率
def recall_score(y_true, y_predict):
assert len(y_true) == len(y_predict)
tp = TP(y_true, y_predict)
fn = FN(y_true, y_predict)
try:
return tp / (tp + fn)
except:
return 0.0
# f1_score
def f1_score(y_true, y_predict):
precision = precision_score(y_true, y_predict)
recall = recall_score(y_true, y_predict)
try:
return 2. * precision * recall / (precision + recall)
except:
return 0.0
def TPR(y_true, y_predict):
tp = TP(y_true, y_predict)
fn = FN(y_true, y_predict)
try:
return tp / (tp + fn)
except:
return 0.0
def FPR(y_true, y_predict):
tn = TN(y_true, y_predict)
fp = FP(y_true, y_predict)
try:
return fp / (tn + fp)
except:
return 0.0
那么 ROC 的应用场合在哪里呢?就在于比较两个模型的孰优孰劣。比如下面这个图。
这两根曲线就代表了两个模型,或者是同一个模型由两组超参数得到的模型,这种情况下,我们应该选择曲线下面面积(曲线与
x
x
x 轴和
x
=
1
x = 1
x=1 所围的面积)更大的那个模型,我们认为这个模型相应的是一个更好的模型。
至此,我们谈论的都是二分类问题,下一篇博客将会谈论在多分类问题的情况。
具体代码见 66 ROC曲线.ipynb