average_precision_score()函数----计算过程与原理详解

这篇具有很好参考价值的文章主要介绍了average_precision_score()函数----计算过程与原理详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近在复现论文时发现作者使用了 sklearn.metrics 库中的 average_precision_score() 函数用来对分类模型进行评价。

看了很多博文都未明白其原理与作用,看了sklean官方文档也未明白,直至在google上找到这篇文章Evaluating Object Detection Models Using Mean Average Precision (mAP),才恍然大悟,现作简单翻译与记录。


首先先说明一下计算的过程:
  1. 使用模型生成预测分数
  2. 通过使用阈值将预测分数转化为类别标签
  3. 计算混淆矩阵
  4. 计算对应的精确率召回率
  5. 创建精确率-召回率曲线
  6. 计算平均精度

接下来分为三个阶段讲解:

从预测分数到类别标签(From Prediction Score to Class Label)

在本节中,我们将快速回顾一下如何从预测分数中派生出类标签。

假设有两个类别,Positive 和 Negative,这里是 10 个样本的真实标签。

y_true = ["positive", "negative", "negative", "positive", "positive", "positive", "negative", "positive", "negative", "positive"]

当这些样本被输入模型时,它会返回以下预测分数。基于这些分数,我们如何对样本进行分类(即为每个样本分配一个类标签)?

pred_scores = [0.7, 0.3, 0.5, 0.6, 0.55, 0.9, 0.4, 0.2, 0.4, 0.3]

为了将预测分数转换为类别标签,使用了一个阈值。当分数等于或高于阈值时,样本被归为一类(通常为正类, 1)。否则,它被归类为其他类别(通常为负类,0)。

以下代码块将分数转换为阈值为 0.5 的类标签。

import numpy

pred_scores = [0.7, 0.3, 0.5, 0.6, 0.55, 0.9, 0.4, 0.2, 0.4, 0.3]
y_true = ["positive", "negative", "negative", "positive", "positive", "positive", "negative", "positive", "negative", "positive"]

threshold = 0.5
y_pred = ["positive" if score >= threshold else "negative" for score in pred_scores]
print(y_pred)

转化后的标签如下:

['positive', 'negative', 'positive', 'positive', 'positive', 'positive', 'negative', 'negative', 'negative', 'negative']

现在 y_truey_pred 变量中都提供了真实标签预测标签

基于这些标签,可以计算出混淆矩阵、精确率和召回率。(可以看这篇博文,讲得很不错,不过混淆矩阵那个图有点小瑕疵)

r = numpy.flip(sklearn.metrics.confusion_matrix(y_true, y_pred))
print(r)

precision = sklearn.metrics.precision_score(y_true=y_true, y_pred=y_pred, pos_label="positive")
print(precision)

recall = sklearn.metrics.recall_score(y_true=y_true, y_pred=y_pred, pos_label="positive")
print(recall)

其结果为

# Confusion Matrix (From Left to Right & Top to Bottom: True Positive, False Negative, False Positive, True Negative)
[[4 2]
 [1 3]]

# Precision = 4/(4+1)
0.8

# Recall = 4/(4+2)
0.6666666666666666

在快速回顾了计算准确率和召回率之后,接下来我们将讨论创建准确率-召回率曲线。

精确度-召回度曲线(Precision-Recall Curve)

根据给出的精度precision和召回率recall的定义,请记住,精度越高,模型将样本分类为阳性时的置信度就越高。召回率越高,模型正确分类为 Positive 的正样本就越多。

当一个模型具有高召回率但低精度时,该模型正确分类了大部分正样本,但它有很多误报(即将许多负样本分类为正样本)。当一个模型具有高精确度但低召回率时,该模型将样本分类为 Positive 时是准确的,但它可能只分类了一些正样本。
注:本人理解,要想一个模型真正达到优秀的效果,精确率和召回率都应较高。

由于准确率和召回率的重要性,一条准确率-召回率曲线可以显示不同阈值的准确率和召回率值之间的权衡。该曲线有助于选择最佳阈值以最大化两个指标。

创建精确召回曲线需要一些输入:

1. 真实标签。
2. 样本的预测分数。
3. 将预测分数转换为类别标签的一些阈值。

下一个代码块创建 y_true 列表来保存真实标签pred_scores 列表用于预测分数,最后是用于不同阈值thresholds 列表。

import numpy

y_true = ["positive", "negative", "negative", "positive", "positive", "positive", "negative", "positive", "negative", "positive", "positive", "positive", "positive", "negative", "negative", "negative"]

pred_scores = [0.7, 0.3, 0.5, 0.6, 0.55, 0.9, 0.4, 0.2, 0.4, 0.3, 0.7, 0.5, 0.8, 0.2, 0.3, 0.35]

thresholds = numpy.arange(start=0.2, stop=0.7, step=0.05)

这是保存在阈值列表中的阈值。因为有 10 个阈值,所以将创建 10 个精度和召回值。

[0.2, 
 0.25, 
 0.3, 
 0.35, 
 0.4, 
 0.45, 
 0.5, 
 0.55, 
 0.6, 
 0.65]

下一个名为 precision_recall_curve() 的函数接收真实标签、预测分数和阈值。它返回两个代表精度和召回值的等长列表。

import sklearn.metrics

def precision_recall_curve(y_true, pred_scores, thresholds):
    precisions = []
    recalls = []
    
    for threshold in thresholds:
        y_pred = ["positive" if score >= threshold else "negative" for score in pred_scores]

        precision = sklearn.metrics.precision_score(y_true=y_true, y_pred=y_pred, pos_label="positive")
        recall = sklearn.metrics.recall_score(y_true=y_true, y_pred=y_pred, pos_label="positive")
        
        precisions.append(precision)
        recalls.append(recall)

    return precisions, recalls

以下代码在传递三个先前准备好的列表后调用 precision_recall_curve() 函数。它返回精度和召回列表,分别包含精度和召回的所有值。

precisions, recalls = precision_recall_curve(y_true=y_true, 
                                             pred_scores=pred_scores,
                                             thresholds=thresholds)

以下是精度precision列表中的返回值

[0.5625,
 0.5714285714285714,
 0.5714285714285714,
 0.6363636363636364,
 0.7,
 0.875,
 0.875,
 1.0,
 1.0,
 1.0]

这是召回recall列表中的值列表

[1.0,
 0.8888888888888888,
 0.8888888888888888,
 0.7777777777777778,
 0.7777777777777778,
 0.7777777777777778,
 0.7777777777777778,
 0.6666666666666666,
 0.5555555555555556,
 0.4444444444444444]

给定两个长度相等的列表,可以在二维图中绘制它们的值,如下所示

matplotlib.pyplot.plot(recalls, precisions, linewidth=4, color="red")
matplotlib.pyplot.xlabel("Recall", fontsize=12, fontweight='bold')
matplotlib.pyplot.ylabel("Precision", fontsize=12, fontweight='bold')
matplotlib.pyplot.title("Precision-Recall Curve", fontsize=15, fontweight="bold")
matplotlib.pyplot.show()

准确率-召回率曲线如下图所示。请注意,随着召回率的增加,精度会降低。原因是当正样本数量增加(高召回率)时,正确分类每个样本的准确率降低(低精度)。这是预料之中的,因为当有很多样本时,模型更有可能失败。
average_precision_score,深度学习,自然语言处理(NLP),机器学习,机器学习,python,深度学习

准确率-召回率曲线可以很容易地确定准确率和召回率都高的点。根据上图,最好的点是(recall, precision)=(0.778, 0.875)。

使用上图以图形方式确定精度和召回率的最佳值可能有效,因为曲线并不复杂。更好的方法是使用称为 f1 分数(f1-score) 的指标,它是根据下一个等式计算的。
average_precision_score,深度学习,自然语言处理(NLP),机器学习,机器学习,python,深度学习
f1 指标衡量准确率和召回率之间的平衡。当 f1 的值很高时,这意味着精度和召回率都很高。较低的 f1 分数意味着精确度和召回率之间的失衡更大。

根据前面的例子,f1是根据下面的代码计算出来的。根据 f1 列表中的值,最高分是 0.82352941。它是列表中的第 6 个元素(即索引 5)。召回率和精度列表中的第 6 个元素分别为 0.778 和 0.875。对应的阈值为0.45。

f1 = 2 * ((numpy.array(precisions) * numpy.array(recalls)) / (numpy.array(precisions) + numpy.array(recalls)))

结果如下

[0.72, 
 0.69565217, 
 0.69565217, 
 0.7,
 0.73684211,
 0.82352941, 
 0.82352941, 
 0.8, 
 0.71428571, 
 0.61538462]

下图以蓝色显示了与召回率和准确率之间的最佳平衡相对应的点的位置。总之,平衡精度和召回率的最佳阈值是 0.45,此时精度为 0.875,召回率为 0.778。

matplotlib.pyplot.plot(recalls, precisions, linewidth=4, color="red", zorder=0)
matplotlib.pyplot.scatter(recalls[5], precisions[5], zorder=1, linewidth=6)

matplotlib.pyplot.xlabel("Recall", fontsize=12, fontweight='bold')
matplotlib.pyplot.ylabel("Precision", fontsize=12, fontweight='bold')
matplotlib.pyplot.title("Precision-Recall Curve", fontsize=15, fontweight="bold")
matplotlib.pyplot.show()

average_precision_score,深度学习,自然语言处理(NLP),机器学习,机器学习,python,深度学习
在讨论了精度-召回曲线之后,接下来讨论如何计算平均精度。

平均精度AP(Average Precision)

平均精度(AP)是一种将精度-召回曲线总结为代表所有精度平均值的单一数值的方法。 AP是根据下面的公式计算的。使用一个循环,通过遍历所有的精度precision/召回recall,计算出当前召回和下一次召回之间的差异,然后乘以当前精度。换句话说,Average-Precision是每个阈值的精确度(precision)的加权求和,其中的权重是召回率(recall)的差。

average_precision_score,深度学习,自然语言处理(NLP),机器学习,机器学习,python,深度学习
重要的是,要将召回列表recalls和精确列表precisions分别附加上0和1。例如,如果recalls列表是
0.8 , 0.6 0.8, 0.6 0.8,0.6
为它追加上 0, 就是
0.8 , 0.6 , 0.0 0.8, 0.6, 0.0 0.8,0.6,0.0
同样的,在精度列表precsion中附加1,
0.8 , 0.2 , 1.0 0.8, 0.2, 1.0 0.8,0.2,1.0
鉴于recalls和precisions都是NumPy数组,以上方程根据以下公式执行

AP = numpy.sum((recalls[:-1] - recalls[1:]) * precisions[:-1])

下面是计算AP的完整代码

import numpy
import sklearn.metrics

def precision_recall_curve(y_true, pred_scores, thresholds):
    precisions = []
    recalls = []
    
    for threshold in thresholds:
        y_pred = ["positive" if score >= threshold else "negative" for score in pred_scores]

        precision = sklearn.metrics.precision_score(y_true=y_true, y_pred=y_pred, pos_label="positive")
        recall = sklearn.metrics.recall_score(y_true=y_true, y_pred=y_pred, pos_label="positive")
        
        precisions.append(precision)
        recalls.append(recall**

    return precisions, recalls

y_true = ["positive", "negative", "negative", "positive", "positive", "positive", "negative", "positive", "negative", "positive", "positive", "positive", "positive", "negative", "negative", "negative"]
pred_scores = [0.7, 0.3, 0.5, 0.6, 0.55, 0.9, 0.4, 0.2, 0.4, 0.3, 0.7, 0.5, 0.8, 0.2, 0.3, 0.35]
thresholds=numpy.arange(start=0.2, stop=0.7, step=0.05)

precisions, recalls = precision_recall_curve(y_true=y_true, 
                                             pred_scores=pred_scores, 
                                             thresholds=thresholds)

precisions.append(1)
recalls.append(0)

precisions = numpy.array(precisions)
recalls = numpy.array(recalls)

AP = numpy.sum((recalls[:-1] - recalls[1:]) * precisions[:-1])
print(AP)

总结

需要注意的是,在 average_precision_score() 函数中,做了一些算法上的调整,与上不同,会将每一个预测分数作为阈值计算对应的精确率precision和召回率recall。最后在长度为 len(预测分数) 的precisions和recalls列表上,应用 Average-Precision 公式,得到最终 Average-Precision 值。

验证函数是否与该算法对照

现在从sklean的官方文档中,得到该函数的使用用例,如下(官方链接)
average_precision_score,深度学习,自然语言处理(NLP),机器学习,机器学习,python,深度学习
现在用以上的算法思想计算

import sklearn.metrics

'''
计算在给定阈值thresholds下的所有精确率与召回率
'''
def precision_recall_curve(y_true, pred_scores, thresholds):
    precisions = []
    recalls = []
    
    for threshold in thresholds:
        y_pred = [1 if score >= threshold else 0 for score in pred_scores]                           # 对此处稍微做修改
        print('y_true is:', y_true)
        print('y_pred is:', y_pred)
        
        confusion_matrix = sklearn.metrics.confusion_matrix(y_true, y_pred)                          # 输出混淆矩阵 
        precision = sklearn.metrics.precision_score(y_true=y_true, y_pred=y_pred)                    # 输出精确率
        recall = sklearn.metrics.recall_score(y_true=y_true, y_pred=y_pred)                          # 输出召回率
        
        print('confusion_matrix is:', confusion_matrix)
        print('precision is:', precision)
        print('recall is:', recall)
        
        precisions.append(precision)
        recalls.append(recall)                                                                       # 追加精确率与召回率
        
        print('\n')
        
    return precisions, recalls

计算每个阈值对应的精确率与召回率,最后得到precisions, recalls

precisions, recalls = precision_recall_curve([0, 0, 1, 1], [0.1, 0.4, 0.35, 0.8], [0.1, 0.4, 0.35, 0.8])

'''
结果
y_true is: [0, 0, 1, 1]
y_pred is: [1, 1, 1, 1]
confusion_matrix is: [[0 2] [0 2]]
precision is: 0.5
recall is: 1.0


y_true is: [0, 0, 1, 1]
y_pred is: [0, 1, 0, 1]
confusion_matrix is: [[1 1] [1 1]]
precision is: 0.5
recall is: 0.5


y_true is: [0, 0, 1, 1]
y_pred is: [0, 1, 1, 1]
confusion_matrix is: [[1 1] [0 2]]
precision is: 0.6666666666666666
recall is: 1.0


y_true is: [0, 0, 1, 1]
y_pred is: [0, 0, 0, 1]
confusion_matrix is: [[2 0] [1 1]]
precision is: 1.0
recall is: 0.5
'''

precisions列表与recalls列表分别追加1, 0,输出precisions列表与recalls列表

precisions.append(1), recalls.append(0)
precisions, recalls
'''
结果
([0.5, 0.5, 0.6666666666666666, 1.0, 1], [1.0, 0.5, 1.0, 0.5, 0])
'''

代入Average-Precision公式,得

average_precision_score,深度学习,自然语言处理(NLP),机器学习,机器学习,python,深度学习

avg_precision = 0                                         # 初始化结果为0

# 不断加权求和
for i in range(len(precisions)-1):
    avg_precision += precisions[i] * (recalls[i] - recalls[i+1])

print('avg_precision is:', avg_precision)                 # 输出结果 

输出结果为

avg_precision is: 0.8333333333333333

可以看到,和sklearn.matrics.average_precision_score()算法的执行结果一致,故正确。

结语

以上内容均为认真查看资料并计算得出的,可能会存在不正确的地方,如有小伙伴存在异议,请留言评论!文章来源地址https://www.toymoban.com/news/detail-838112.html

到了这里,关于average_precision_score()函数----计算过程与原理详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第二章第14节:EXCEL :计算Excel求平均函数函数AVERAGE 、AVERAGEIF、AVERAGEIFS函数

    它们分别是AVERAGE 、AVERAGEIF、AVERAGEIFS函数, 它们的区别是:AVERAGE是直接求平均值; AVERAGEIF单条件求平均值; AVERAGEIFS多个条件求平均值。 求出所有参数的算术平均值。如果某个单元格是空的或包含文本,它将不用于计算平均数。如果单元格数值为0,将参于计算平均数 。 【

    2024年01月23日
    浏览(47)
  • Spark - AUC、Accuracy、Precision、Recall、F1-Score 理论与实战

    推荐场景下需要使用上述指标评估离、在线模型效果,下面对各个指标做简单说明并通过 spark 程序全部搞定。 搜广推场景下最常见的就是 Ctr 2 分类场景,对于真实值 real 和预测值 pre 分别有 0 和 1 两种可能,从而最终 2x2 产生 4 种可能性: - TP 真正率 对的预测对 ,即 1 预测

    2024年02月02日
    浏览(42)
  • 分类模型评估(混淆矩阵, precision, recall, f1-score)的原理和Python实现

    当我们已经获取到一个分类模型的预测值,可以通过不同指标来进行评估。 往往衡量二分类模型是基于以下的混淆矩阵概念: True Positive:真实值为正、预测值为正(真阳性) False Positive:真实值为负、预测值为正(假阳性) False Negative:真实值为正、预测值为负(假阴性)

    2024年02月04日
    浏览(49)
  • YOLO 模型的评估指标——IOU、Precision、Recall、F1-score、mAP

    YOLO是最先进的目标检测模型之一。目标检测问题相比分类问题要更加复杂,因为目标检测不仅要把类别预测正确,还要预测出这个类别具体在哪个位置。 我将目标识别的评估指标总结为两部分,一部分为预测框的预测指标,另一部分为分类预测指标。 预测框的准确率用IOU来

    2024年02月04日
    浏览(51)
  • 分类问题的评价指标(Precision、Recall、Accuracy、F1-Score、Micro-F1、Macro-F1)以及混淆矩阵、ROC曲线

    真阳性:预测为正,实际为正。把正样本 成功 预测为正。  TP ——True Positive 假阳性:预测为正,实际为负。把负样本 错误 预测为正。  FP ——False Positive  ——误报 真阴性:预测为负、实际为负。把负样本 成功 预测为负。  TN ——True Negative 假阴性:预测与负、实际

    2024年01月19日
    浏览(44)
  • accuracy_score函数

    sklearn中accuracy_score函数计算了准确率。 在二分类或者多分类中,预测得到的label,跟真实label比较,计算准确率。 在multilabel(多标签问题)分类中,该函数会返回子集的准确率。如果对于一个样本来说,必须严格匹配真实数据集中的label,整个集合的预测标签返回1.0;否则返

    2024年02月02日
    浏览(39)
  • MATLAB知识点:mean : 计算平均值(mean/average value)

    ​讲解视频:可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇(数学建模清风主讲,适合零基础同学观看)_哔哩哔哩_bilibili 节选自第3章 3.4.1节 假设向量 ,即向量y有n个元素,那么它的平均值等于. 在MATLAB中,mean函数可以用来计算

    2024年04月09日
    浏览(75)
  • 基于sklearn计算precision、recall等分类指标

    在前面的文章中,我们已经介绍了分类指标Precision,Recall,F1-Score的定义和计算公式:详解分类指标Precision,Recall,F1-Score 我们可以知道, 精度(precision)、查全率(recall)、F1的计算,是针对于二分类器来定义的。他们的计算,只与y_true和y_pred有关,要求y_true和y_pred中只含有0和

    2024年02月16日
    浏览(39)
  • 从源码理解Scala中函数reduceRight的计算过程

    水善利万物而不争,处众人之所恶,故几于道💦   以List集合为例,进行reduceRight()的计算过程分析,总体分为两部分,一部分是看最顶层特质的那个通用的reduceRight方法,另一部分是讲直接混入的特质的那个重写的reduceRight方法,两种方式最终结果一致。 例如:   上面的

    2024年02月17日
    浏览(37)
  • pytorch中torch.einsum函数的详细计算过程图解

    第一次见到 rel_h = torch.einsum(“bhwc,hkc-bhwk”, r_q, Rh)这行代码时,属实是懵了,网上找了很多博主的介绍,但都没有详细的说明函数内部的计算过程,看得我是一头雾水,只知道计算结果的维度是如何变化的,却不明白函数内部是如何计算的。话不多说,直接上示例代码 输出结

    2024年02月14日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包