深度学习评价指标

Posted ylfmsn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度学习评价指标相关的知识,希望对你有一定的参考价值。

图像分类评测指标

1.TP、TN、FP、FN

  • TP(True Positives)倒着来翻译就是“预测为正样本,并且预测对了”(真阳性)
  • TN(True Negatives)意思是“预测为负样本,而且预测对了”(真阴性)
  • FP(False Positives)意思是“预测为正样本,但是预测错了”(假阳性)
  • FN(False Negatives)意思是“预测喂负样本,但是预测错了”(假阴性)

要记住这一点,有两个技巧(拿核酸检测举例):

  • 如果以True开头,则无论是否患有新冠,预测都是正确的,因此真正的阳性就是正确预测的新冠患者,真正的阴性是正确预测的健康人。相反,如果以False开头,则预测不正确,因此假阳性是健康人被错误预测成了新冠患者,假阴性是新冠患者被错误预测为健康。
  • Positives或Negatives表示检测程序的输出。而true或false判断此输出是否正确

2.混淆矩阵

在机器学习领域,特别是统计分类问题中,混淆矩阵,也称为误差矩阵,是一种特定的表格布局,允许可视化,通常是监督学习算法(在无监督学习一般叫做匹配矩阵)。矩阵的每一行代表预测类中的实例,而每一列代表实际类中的实例(反之亦然)。这个名称源于这样一个事实,即它可以很容易地看出系统是否混淆了两个类(即通常将一个错误标记为另一个)。(维基百科定义)

如果想知道类别之间相互误分的情况,查看是否有特定的类别相互混淆,可以用混淆矩阵画出分类的详细预测结果。对于包含多个类别的任务,可以很清晰的反映各类别之间的错分概率。
比如一个模型对15个样本进行预测,然后结果如下:

  • 预测值: 1 1 1 1 1 0 0 0 0 0 1 1 1 0 1
  • 真实值: 0 1 1 0 1 1 0 0 1 0 1 0 1 0 0
预测值=1预测值=0
真实值=152
真实值=044
预测值=1预测值=0
真实值=1TPFN
真实值=0FPTN

3.准确率(Accuracy)、精确率(Precision)、召回率(Recall)、F1-score

Accuracy = (TP + TN) / (P + N) (所有预测正确的正例和负例,占所有样本的比例)

# 代码为torch版本
# 其中 SR 为预测的mask,即 Segmentation Result
# 其中 GT 为真实的标注,即 Ground Truth
def get_accuracy(SR,GT,threshold=0.5):
    SR = SR > threshold
    GT = GT == torch.max(GT)
    corr = torch.sum(SR==GT)
    tensor_size = SR.size(0)*SR.size(1)*SR.size(2)*SR.size(3)
    acc = float(corr)/float(tensor_size)

    return acc

Precision = TP / (TP + FP) (预测为正例并且确实是正例的部分,占所有预测为正例的比例)

# 代码为torch版本
# 其中SR为预测的mask,即Segmentation Result
# 其中GT为真实的标注,即Ground Truth
def get_precision(SR, GT, threshold=0.5):
    SR = SR > threshold
    GT = GT == torch.max(GT)
    TP = ((SR == 1) & (GT == 1))
    FP = ((SR == 1) & (GT == 0))
    PC = float(torch.sum(TP)) / (float(torch.sum(TP + FP)) + 1e-6)

    return PC

Recall = TP / (TP + FN) (预测为正例并且确实是正例的部分,占所有确实是正例的比例)

# 代码,同灵敏度

F1_score = 2 / ((1/Precision) + (1/Recall)) = 2TP / (FP + 2TP + FN) (精准率与召回率的调和平均)

# 代码为torch版本
# 其中SR为预测的mask,即Segmentation Result
# 其中GT为真实的标注,即Ground Truth
def get_F1(SR, GT, threshold=0.5):
    SE = get_sensitivity(SR, GT, threshold=threshold)
    PC = get_precision(SR, GT, threshold=threshold)
    F1 = 2 * SE * PC / (SE + PC + 1e-6)

    return F1

4.灵敏度(Sensitivity)、特异度(Specificity)

Sensitivity = TP / (TP + FN) = Recall (灵敏度,同召回率)

# 代码为torch版本
# 其中SR为预测的mask,即Segmentation Result
# 其中GT为真实的标注,即Ground Truth
# Sensitivity == Recall
def get_sensitivity(SR, GT, threshold=0.5):
    SR = SR > threshold
    GT = GT == torch.max(GT)
    TP = ((SR == 1) & (GT == 1))
    FN = ((SR == 0) & (GT == 1))
    SE = float(torch.sum(TP)) / (float(torch.sum(TP + FN)) + 1e-6)

    return SE

Specificity = TN / (TN + FP) (预测为负例并且确实是负例的部分,占所有确实为负例的比例)

# 代码为torch版本
# 其中SR为预测的mask,即Segmentation Result
# 其中GT为真实的标注,即Ground Truth
def get_specificity(SR, GT, threshold=0.5):
    SR = SR > threshold
    GT = GT == torch.max(GT)
    TN = ((SR == 0) & (GT == 0))
    FP = ((SR == 1) & (GT == 0))
    SP = float(torch.sum(TN)) / (float(torch.sum(TN + FP)) + 1e-6)

    return SP

以下为预测荒地后的一个评估结果

[
    
        "class_id": 0,
        "class_name": "background",
        "gt_count": 84041442.0,
        "pred_count": 82820222.0,
        "count_error": 1221220.0,
        "relative_frequency": 0.9875540710066456,
        "metrics": 
            "recall": 0.9787523517266636,
            "precision": 0.9931844785443825,
            "f1": 0.9859156025197017,
            "sensitivity": 0.9787523517266636,
            "specificity": 0.46706339764869387
        ,
        "conf_mat": [
            [
                494693.0,
                564463.0
            ],
            [
                1785683.0,
                82255759.0
            ]
        ],
        "conf_mat_frac": [
            [
                0.005813037882530508,
                0.006632891110823921
            ],
            [
                0.02098320155165067,
                0.9665708694549949
            ]
        ],
        "conf_mat_dict": 
            "TN": 494693.0,
            "FP": 564463.0,
            "FN": 1785683.0,
            "TP": 82255759.0
        ,
        "conf_mat_frac_dict": 
            "TN": 0.005813037882530508,
            "FP": 0.006632891110823921,
            "FN": 0.02098320155165067,
            "TP": 0.9665708694549949
        
    ,
    
        "class_id": 1,
        "class_name": "polygons",
        "gt_count": 1059156.0,
        "pred_count": 2280376.0,
        "count_error": 1221220.0,
        "relative_frequency": 0.01244592899335443,
        "metrics": 
            "recall": 0.46706339764869387,
            "precision": 0.2169348388160549,
            "f1": 0.2962648658554552,
            "sensitivity": 0.46706339764869387,
            "specificity": 0.9787523517266636
        ,
        "conf_mat": [
            [
                82255759.0,
                1785683.0
            ],
            [
                564463.0,
                494693.0
            ]
        ],
        "conf_mat_frac": [
            [
                0.9665708694549949,
                0.02098320155165067
            ],
            [
                0.006632891110823921,
                0.005813037882530508
            ]
        ],
        "conf_mat_dict": 
            "TN": 82255759.0,
            "FP": 1785683.0,
            "FN": 564463.0,
            "TP": 494693.0
        ,
        "conf_mat_frac_dict": 
            "TN": 0.9665708694549949,
            "FP": 0.02098320155165067,
            "FN": 0.006632891110823921,
            "TP": 0.005813037882530508
        
    ,
    
        "class_name": "average",
        "metrics": 
            "recall": 0.9723839073375254,
            "precision": 0.9835233306472069,
            "f1": 0.9773322584209639,
            "sensitivity": 0.9723839073375254,
            "specificity": 0.47343184203783206
        ,
        "gt_count": 85100598.0,
        "pred_count": 85100598.0,
        "count_error": 2442440.0,
        "conf_mat": [
            [
                82255759.0,
                1785683.0
            ],
            [
                564463.0,
                494693.0
            ]
        ],
        "conf_mat_frac": [
            [
                0.9665708694549949,
                0.02098320155165067
            ],
            [
                0.006632891110823921,
                0.005813037882530508
            ]
        ]
    
]

Python 深度学习目标检测评价指标

目标检测评价指标:

准确率 (Accuracy),混淆矩阵 (Confusion Matrix),精确率(Precision),召回率(Recall),平均正确率(AP),mean Average Precision(mAP),交除并(IoU),ROC + AUC,非极大值抑制(NMS)。

假设原始样本中有两类,其中: 
  1:总共有 P 个类别为 1 的样本,假设类别 1 为正例。 
  2:总共有 N 个类别为 0 的样本,假设类别 0 为负例。 
经过分类后: 
  3:有 TP 个类别为 1 的样本被系统正确判定为类别 1,FN 个类别为 1 的样本被系统误判定为类别 0,显然有 P=TP+FN; 
  4:有 FP 个类别为 0 的样本被系统误判断定为类别 1,TN 个类别为 0 的样本被系统正确判为类别 0,显然有 N=FP+TN; 

                                                                  GroundTruth           预测结果

TP(True Positives):   真的正样本  = 【正样本  被正确分为  正样本】

TN(True Negatives):真的负样本  = 【负样本  被正确分为  负样本】

FP(False Positives):  假的正样本  = 【负样本  被错误分为  正样本】

FN(False Negatives):假的负样本  = 【正样本  被错误分为  负样本】

Python


1、准确率 (Accuracy)

  A = (TP + TN)/(P+N) = (TP + TN)/(TP + FN + FP + TN);
  反映了分类器统对整个样本的判定能力——能将正的判定为正,负的判定为负。

2、精确度(Precision)

        P = TP/(TP+FP);

       分对的样本数除以所有的样本数 ,即:准确(分类)率 = 正确预测的正反例数 / 总数。

  准确率一般用来评估模型的全局准确程度,不能包含太多信息,无法全面评价一个模型性能。

       反映了被分类器判定的正例中真正的正例样本的比重。

3、召回率(recall)

        R = TP/(TP+FN) = 1 - FN/T;
  反映了被正确判定的正例占总的正例的比重。

4、F1值 

       F1 = 2 * 召回率 * 准确率 / (召回率 + 准确率);

       这就是传统上通常说的 F1 measure。

5、漏警概率(Missing Alarm)

       MA = FN/(TP + FN) = 1–TP/T = 1-R;
       反映有多少个正例被漏判。

6、虚警概率(False Alarm)

       FA = FP/(TP + FP) = 1–P;
       反映有多少个负例被误判。

7、混淆矩阵 (Confusion Matrix)

  混淆矩阵中的横轴是模型预测的类别数量统计,纵轴是数据真实标签的数量统计。

  对角线,表示模型预测和数据标签一致的数目,所以对角线之和除以测试集总数就是准确率。对角线上数字越大越好,在可视化结果中颜色越深,说明模型在该类的预测准确率越高。如果按行来看,每行不在对角线位置的就是错误预测的类别。总的来说,我们希望对角线越高越好,非对角线越低越好。

8、精确率(Precision)与召回率(Recall)

  

Python

  一些相关的定义。假设现在有这样一个测试集,测试集中的图片只由大雁和飞机两种图片组成,假设你的分类系统最终的目的是:能取出测试集中所有飞机的图片,而不是大雁的图片。

  • True positives : 正样本被正确识别为正样本,飞机的图片被正确的识别成了飞机。
  • True negatives: 负样本被正确识别为负样本,大雁的图片没有被识别出来,系统正确地认为它们是大雁。
  • False positives: 假的正样本,即负样本被错误识别为正样本,大雁的图片被错误地识别成了飞机。
  • False negatives: 假的负样本,即正样本被错误识别为负样本,飞机的图片没有被识别出来,系统错误地认为它们是大雁。

  Precision其实就是在识别出来的图片中,True positives所占的比率。也就是本假设中,所有被识别出来的飞机中,真正的飞机所占的比例。反映了被分类器判定的正例中真正的正例样本的比重。

Python

  Recall 是测试集中所有正样本样例中,被正确识别为正样本的比例。也就是本假设中,被正确识别出来的飞机个数与测试集中所有真实飞机的个数的比值。

Python

  Precision-recall 曲线:改变识别阈值,使得系统依次能够识别前K张图片,阈值的变化同时会导致Precision与Recall值发生变化,从而得到曲线。

  如果一个分类器的性能比较好,那么它应该有如下的表现:在Recall值增长的同时,Precision的值保持在一个很高的水平。而性能比较差的分类器可能会损失很多Precision值才能换来Recall值的提高。通常情况下,文章中都会使用Precision-recall曲线,来显示出分类器在Precision与Recall之间的权衡。

9、平均精度(Average-Precision,AP)与 mean Average Precision(mAP)

  AP就是Precision-recall 曲线下面的面积,通常来说一个越好的分类器,AP值越高。

  mAP是多个类别AP的平均值。这个mean的意思是对每个类的AP再求平均,得到的就是mAP的值,mAP的大小一定在[0,1]区间,越大越好。该指标是目标检测算法中最重要的一个。

  在正样本非常少的情况下,PR表现的效果会更好。

  Python

10、IoU

  IoU这一值,可以理解为系统预测出来的框与原来图片中标记的框的重合程度。 计算方法即检测结果Detection Result与 Ground Truth 的交集比上它们的并集,即为检测的准确率。

       值得注意的是,IoU值超过0.5时,主观效果已经比较不错。

  IOU正是表达这种bounding box和groundtruth的差异的指标:


11、ROC(Receiver Operating Characteristic)曲线与AUC(Area Under Curve)

     

Python

  ROC曲线:

  • 横坐标:假正率(False positive rate, FPR),FPR = FP / [ FP + TN] ,代表所有负样本中错误预测为正样本的概率,假警报率;
  • 纵坐标:真正率(True positive rate, TPR),TPR  = TP / [ TP + FN] ,代表所有正样本中预测正确的概率,命中率。

  对角线对应于随机猜测模型,而(0,1)对应于所有整理排在所有反例之前的理想模型。曲线越接近左上角,分类器的性能越好。

  ROC曲线有个很好的特性:当测试集中的正负样本的分布变化的时候,ROC曲线能够保持不变。在实际的数据集中经常会出现类不平衡(class imbalance)现象,即负样本比正样本多很多(或者相反),而且测试数据中的正负样本的分布也可能随着时间变化。

  ROC曲线绘制:

  (1)根据每个测试样本属于正样本的概率值从大到小排序;

  (2)从高到低,依次将“Score”值作为阈值threshold,当测试样本属于正样本的概率大于或等于这个threshold时,我们认为它为正样本,否则为负样本;

  (3)每次选取一个不同的threshold,我们就可以得到一组FPR和TPR,即ROC曲线上的一点。 

   当我们将threshold设置为1和0时,分别可以得到ROC曲线上的(0,0)和(1,1)两个点。将这些(FPR,TPR)对连接起来,就得到了ROC曲线。当threshold取值越多,ROC曲线越平滑。

   AUC(Area Under Curve)即为ROC曲线下的面积。AUC越接近于1,分类器性能越好。

   物理意义:首先AUC值是一个概率值,当你随机挑选一个正样本以及一个负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值。当然,AUC值越大,当前的分类算法越有可能将正样本排在负样本前面,即能够更好的分类。

  计算公式:就是求曲线下矩形面积。

Python

 12、PR曲线和ROC曲线比较

  ROC曲线特点:

  (1)优点:当测试集中的正负样本的分布变化的时候,ROC曲线能够保持不变。因为TPR聚焦于正例,FPR聚焦于与负例,使其成为一个比较均衡的评估方法。

      在实际的数据集中经常会出现类不平衡(class imbalance)现象,即负样本比正样本多很多(或者相反),而且测试数据中的正负样本的分布也可能随着时间变化。

  (2)缺点:上文提到ROC曲线的优点是不会随着类别分布的改变而改变,但这在某种程度上也是其缺点。因为负例N增加了很多,而曲线却没变,这等于产生了大量FP。像信息检索中如果主要关心正例的预测准确性的话,这就不可接受了。在类别不平衡的背景下,负例的数目众多致使FPR的增长不明显,导致ROC曲线呈现一个过分乐观的效果估计。ROC曲线的横轴采用FPR,根据FPR ,当负例N的数量远超正例P时,FP的大幅增长只能换来FPR的微小改变。结果是虽然大量负例被错判成正例,在ROC曲线上却无法直观地看出来。(当然也可以只分析ROC曲线左边一小段)

  PR曲线:

  (1)PR曲线使用了Precision,因此PR曲线的两个指标都聚焦于正例。类别不平衡问题中由于主要关心正例,所以在此情况下PR曲线被广泛认为优于ROC曲线。

  使用场景:

  1. ROC曲线由于兼顾正例与负例,所以适用于评估分类器的整体性能,相比而言PR曲线完全聚焦于正例。
  2. 如果有多份数据且存在不同的类别分布,比如信用卡欺诈问题中每个月正例和负例的比例可能都不相同,这时候如果只想单纯地比较分类器的性能且剔除类别分布改变的影响,则ROC曲线比较适合,因为类别分布改变可能使得PR曲线发生变化时好时坏,这种时候难以进行模型比较;反之,如果想测试不同类别分布下对分类器的性能的影响,则PR曲线比较适合。
  3. 如果想要评估在相同的类别分布下正例的预测情况,则宜选PR曲线。
  4. 类别不平衡问题中,ROC曲线通常会给出一个乐观的效果估计,所以大部分时候还是PR曲线更好。
  5. 最后可以根据具体的应用,在曲线上找到最优的点,得到相对应的precision,recall,f1 score等指标,去调整模型的阈值,从而得到一个符合具体应用的模型。

 13、非极大值抑制(NMS)

   Non-Maximum Suppression就是需要根据score矩阵和region的坐标信息,从中找到置信度比较高的bounding box。对于有重叠在一起的预测框,只保留得分最高的那个。

  (1)NMS计算出每一个bounding box的面积,然后根据score进行排序,把score最大的bounding box作为队列中首个要比较的对象;

  (2)计算其余bounding box与当前最大score与box的IoU,去除IoU大于设定的阈值的bounding box,保留小的IoU得预测框;

  (3)然后重复上面的过程,直至候选bounding box为空。

  最终,检测了bounding box的过程中有两个阈值,一个就是IoU,另一个是在过程之后,从候选的bounding box中剔除score小于阈值的bounding box。需要注意的是:Non-Maximum Suppression一次处理一个类别,如果有N个类别,Non-Maximum Suppression就需要执行N次。


以上是关于深度学习评价指标的主要内容,如果未能解决你的问题,请参考以下文章

Python深度学习之路-3.1性能评价指标

Python 深度学习目标检测评价指标

Python 深度学习目标检测评价指标

A.深度学习基础入门篇[二]:机器学习常用评估指标:AUCmAPISFIDPerplexityBLEUROUGE等详解

深度学习目标检测之评价指标

深度学习分类任务评价指标