评估指标(二)| F1分数、AUC

1,100 阅读1分钟

专栏的评估指标相关文章。

评估指标(一)| 准确率、精确率、召回率

书接上文,我们已经讨论了准确率、精确率和召回率,本文将讨论 F1 分数AUC 这两种常用指标。

1 F1分数

F1 分数是精确率和召回率的综合指标,它被定义为精确率和召回率的简单加权平均值(调和平均值),是统计学中用来衡量二分类模型精确度的一种指标。如果我们用 PP 表示精确率,用 RR 表示召回率,那么 F1 分数可以表示为:

F1=2PRP+RF1=\frac{2PR}{P+R}

用 Python 实现如下。

def f1(y_true, y_pred):
    p = precision(y_true, y_pred)
    r = recall(y_true, y_pred)
    # 计算f1分数值
    score = 2 * p * r / (p + r)
    return score
In [X]: f1(l1, l2)
Out[X]: 0.5714285714285715

运行程序,我们便能够得到该模型的 F1 分数。F1 分数的最大值是 11,最小值是 00,通常来说,越接近 11,说明模型的性能越好,能够更准确地预测正例。

2 AUC

在学习 AUC 之前,我们得先了解另外两个术语 TPRFPR

2.1 TPR

TPR 或称真阳性率(True Positive Rate),它与召回率相同,即表达式一样。它指的是所有实际为阳性的样本被正确地判断为阳性的个数与所有实际为阳性的样本个数之比

TPR=TPTP+FNTPR=\frac{TP}{TP+FN}

因为TPR与召回率相当,所以它的 Python 实现很简单。

def tpr(y_true, y_pred):
    return recall(y_true, y_pred)

另外,TPR 或召回率也被称为灵敏度。

2.2 FPR

FPR 或称假阳性率(False Positive Rate),它的含义是所有实际为阴性的样本被错误地判断为阳性的个数与所有实际为阴性的样本个数之比

FPR=FPFP+TNFPR=\frac{FP}{FP+TN}

FPR 的 Python 实现如下。

def fpr(y_true, y_pred):
    fp = false_positive(y_true, y_pred)
    tn = true_negative(y_true, y_pred)
    # 计算假阳性率
    return fp / (fp + tn)

2.3 ROC曲线和AUC

对于之前的讨论,我们都是立足在一个预测结果只为 0011 的模型 AA 上。现在我们要提出另外一个模型 BB。假设我们只有 1515 个样本,其标签值是二元的。同时,我们训练了一个类似于随机森林的模型 BB,并得到了样本呈正例的概率。

# 真实样本标签
y_true = [0, 0, 0, 0, 1, 0, 1,0, 0, 1, 0, 1, 0, 0, 1]
#预测样本为正例(1)的概率
y_pred = [0.1, 0.3, 0.2, 0.6, 0.8, 0.05,
          0.9, 0.5, 0.3, 0.66, 0.3, 0.2,
          0.85, 0.15, 0.99]

为了评估该模型的精确率、召回率和 FPR 等数值,我们需要选择一定的阈值,有一个简单的方法就是选取 0.5\geq0.5 的典型阈值。但事实上,我们可以选择从 0011 之间的任何值作为阈值,以全面地评估模型。

# 预测阈值
thresholds = [0, 0.1, 0.2, 0.3, 0.4, 0.5,
             0.6, 0.7, 0.8, 0.85, 0.9, 0.99, 1.0]

接下来,我们计算该模型在不同阈值下的 TPR 和 FPR。

tpr_list = []
fpr_list = []

for thresh in thresholds:
    # 若样本为正例(1)的概率大于等于阈值,为1,否则为0
    temp_pred = [1 if x >= thresh else 0 for x in y_pred]

    temp_tpr = tpr(y_true, temp_pred)
    temp_fpr = fpr(y_true, temp_pred)

    tpr_list.append(temp_tpr)
    fpr_list.append(temp_fpr)

最后,我们将 tpr_listtpr\_listfpr_listfpr\_list 两个列表以散点图的形式绘制出来。

import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

plt.figure(figsize=(5, 5))
sns.set_style('white')
plt.plot(fpr_list, tpr_list)
plt.fill_between(fpr_list, tpr_list, color='lightblue')
plt.xlabel("FPR", size=15)
plt.ylabel("TPR", size=15)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.0])
plt.show()

art_2_pic1.png

如图所示,这条从原点出发的曲线就是 ROC 曲线。如果我们计算这条 ROC 曲线下的面积,即图中浅蓝色的多边形,就是在计算另一个指标——AUC。在这里我们利用 scikit-learn 库现成的函数来计算 AUC 值。

In [X]: from sklearn import metrics
In [X]: metrics.roc_auc_score(y_true, y_pred)
Out[X]: 0.8300000000000001

运行程序,输出 AUC 值为 0.830.83。这是好还是坏呢?

AUC 是一种用于评估二分类模型性能的指标。它反映了模型在所有可能的阈值下的总体性能,较高的 AUC 值通常表示模型在区分正例和负例方面表现较好。AUC 的取值范围在 0011 之间,0.50.5 表示模型的性能与随机猜测相同,11 则表示模型可以完美地将正例和负例区分开来,如果是 00 的话则意味着这个模型非常糟糕。所以我们训练的模型效果还算良好。

但 AUC 对我们的模型有什么影响呢?

假设我们刚才建立的是一个从图片中检测气球的模型,其 AUC 值为 0.830.83,这意味着随机给定一张带有气球的图片(正样本)和一张不带有气球的图片(负样本),用我们的模型进行分类和预测,正样本的得分比负样本的得分要的概率为 0.830.83

现在,我们已经拥有了 ROC 曲线,那么如何从中挑选出最适合这个模型的阈值呢?

根据先前给出的 TPR 和 FPR 的定义,我们肯定是希望一个模型的 TPR 值较高,FPR 值较低,即模型可以识别更多的正例,带来更少的误报。那么有一个常用的方法——等距最近点法,可以帮助我们选出最合适的阈值。在这个方法中,我们选择 ROC 曲线上离左上角(即 FPR 为 00,TPR 为 11 的点)最近的点对应的阈值作为最佳阈值。这种方法试图在真阳性率和假阳性率之间找到一个平衡,具体也可以通过计算每个点到左上角的欧氏距离来实现,选择距离最小的点所对应的阈值。

import pandas as pd
data = {'threshold':thresholds, 'tpr':tpr_list, 'fpr':fpr_list}
df = pd.DataFrame(data)

运行程序,得到结果如下。

art_2_pic2.png

简单计算一下,可以发现当阈值为 0.60.6 时,模型 BB 的分类效果应该是最好的。

参考文献

F1分数

AUC

roc曲线最佳阈值

Approaching (Almost) Any Machine Learning Problem