关于深度学习:深度学习分类任务常用评估指标

7次阅读

共计 17700 个字符,预计需要花费 45 分钟才能阅读完成。

摘要:这篇文章次要向大家介绍深度学习分类工作评估指标, 次要内容包含根底利用、实用技巧、原理机制等方面,心愿对大家有所帮忙。

本文分享自华为云社区《深度学习分类工作罕用评估指标》,原文作者:lutianfei。

这篇文章次要向大家介绍深度学习分类工作评估指标, 次要内容包含根底利用、实用技巧、原理机制等方面,心愿对大家有所帮忙。

分类模型

混同矩阵

sklearn 实现:

sklearn.metrics.confusion_matrix(y_true, y_pred, labels=None)

返回值:一个格式化的字符串,给出了分类后果的混同矩阵。参数:参考 classification_report。混同矩阵的内容如下,其中 Cij 示意实在标记为 i 然而预测为 j 的样本的数量。Confusion Matrix:

[[5 0]

[3 2]]
def calc_confusion_matrix(y_true: list, y_pred: list, show=True, save=False, figsize=(16, 16), verbose=False):
    """
    计算混同矩阵
    :param y_true: 
    :param y_pred: 
    :param show: 
    :param save: 
    :param figsize: 
    :param verbose: 
    :return: 
    """
    confusion = confusion_matrix(y_true, y_pred)
    if verbose:
        print(confusion)

    if show:
        show_confusion_matrix(confusion, figsize=figsize, save=save)

    return confusion

def show_confusion_matrix(confusion, classes=MY_CLASSES, x_rot=-60, figsize=None, save=False):
    """
    绘制混同矩阵
    :param confusion:
    :param classes:
    :param x_rot:
    :param figsize:
    :param save:
    :return:
    """
    if figsize is not None:
        plt.rcParams['figure.figsize'] = figsize

    plt.imshow(confusion, cmap=plt.cm.YlOrRd)
    indices = range(len(confusion))
    plt.xticks(indices, classes, rotation=x_rot, fontsize=12)
    plt.yticks(indices, classes, fontsize=12)
    plt.colorbar()
    plt.xlabel('y_pred')
    plt.ylabel('y_true')

    # 显示数据
    for first_index in range(len(confusion)):
        for second_index in range(len(confusion[first_index])):
            plt.text(first_index, second_index, confusion[first_index][second_index])

    if save:
        plt.savefig("./confusion_matrix.png")
    plt.show()

混同矩阵是监督学习中的一种可视化工具,次要用于比拟分类后果和实例的实在信息。矩阵中的每一行代表实例的预测类别,每一列代表实例的实在类别。

了解办法:

P(positive):预测为正样本

N(Negative):预测为负样本

T(True):预测正确

F(False):预测谬误

  • 真正(True Positive, TP): 被模型预测为正的正样本。预测为 1,预测正确,即理论 1
  • 假正(False Positive, FP): 被模型预测为正的负样本。预测为 1,预测谬误,即理论 0
  • 假负(False Negative, FN): 被模型预测为负的正样本。预测为 0,预测错确,即理论 1
  • 真负(True Negative, TN): 被模型预测为负的负样本。预测为 0,预测正确即,理论 0

真正率(True Positive Rate, TPR)或灵活率(sensitivity)

TPR= TP/(TP+FN) -> 正样本预测后果数 / 正样本理论数

由上述公式可知 TPR 等价于 Recall

真负率(True Negative Rate, TNR)或 特指度 / 特异度(specificity)

TNR=TN/(TN+FP) -> 负样本预测后果数 / 负样本理论数

假正率(False Positive Rate, FPR)

FPR = FP/(FP+TN) -> 被预测为正的负样本后果数 / 负样本理论数

假负率(False Negative Rate, FNR)

FNR = FN/(TP+FN) -> 被预测为负的正样本后果数 / 正样本理论数

准确率(正确率,Accuracy)

也称正确率,预测正确的后果占总样本的百分比,最罕用的分类性能指标。

公式:Accuracy = (TP+TN)/(TP+FN+FP+FN)

毛病:样本不平衡时有局限性,

例如:当负样本占 99% 时,分类器把所有样本都预测为负样本也能够取得 99% 的准确率。所以,当不同类别的样本比例十分不平衡时,占比大的类别往往成为影响准确率的最次要因素。

sklearn 实现:

from sklearn.metrics import accuracy_score

accuracy_score(y_true, y_pred, normalize=True, sample_weight=None)

返回值:如果 normalize 为 True,则返回准确率;如果 normalize 为 False,则返回正确分类的数量。参数:y_true:实在的标记汇合。y_pred:预测的标记汇合。normalize:一个布尔值,批示是否须要归一化后果。如果为 True,则返回分类正确的比例(准确率)。如果为 False,则返回分类正确的样本数量。sample_weight:样本权重,默认每个样本的权重为 1。# 办法封装
def calc_accuracy_score(y_true: list, y_pred: list, verbose=False):
    res = accuracy_score(y_true, y_pred)
    if verbose:
        print("accuracy:%s" % res)

    return res

错误率(Error rate)

即,谬误预测的正反例数 / 总数。

正确率与错误率是别离从正反两方面进行评估的指标,两者数值相加刚好等于 1。

ErrorRate = (FP+FN)/(TP+FN+FP+TN)

准确率(查准率,Precision)
精准率(Precision)又叫查准率,它是针对预测后果而言的,它的含意是在所有被预测为正的样本中理论为正的样本的概率,意思就是在预测为正样本的后果中,咱们有多少把握能够预测正确,其公式如下:

Precision = TP/(TP+FP)

毛病:预测的后果只有 1 例正例,并且是正确的,精准率为 100%。理论又很多预测谬误的负例,即实在的正例。

场景:预测股票会涨,实在涨了 10 次,只预测到了两次会涨,预测这两次都对了,那么就是咱们想要的精准度高,此时召回率不重要。

sklearn 实现:

from sklearn.metrics import precision_score

sklearn.metrics.precision_score(y_true, y_pred, labels=None, pos_label=1,
average='binary', sample_weight=None)

返回值:查准率。即预测后果为正类的那些样本中,有多少比例的确是正类。参数:y_true:实在的标记汇合。y_pred:预测的标记汇合。labels:一个列表。当 average 不是 'binary' 时应用。对于多分类问题,它示意:将计算哪些类别。不在 labels 中的类别,计算 macro precision
时其成分为 0。对于多标签问题,它示意:待考查的标签的索引。除了 average=None 之外,labels 的元素的程序也十分重要。默认状况下,y_true 和 y_pred 中所有的类别都将被用到。pos_label:一个字符串或者整数,指定哪个标记值属于正类。如果是多分类或者多标签问题,则该参数被疏忽。如果设置 label=[pos_label] 以及 average!='binary' 则会仅仅计算该类别的 precision。average:一个字符串或者 None,用于指定二分类或者多类分类的 precision 如何计算。'binary':计算二类分类的 precision。此时由 pos_label
指定的类为正类,报告其 precision。它要求 y_true、y_pred 的元素都是 0,1。'micro':通过全局的正例和负例,计算 precision。'macro':计算每个类别的 precision,而后返回它们的均值。'weighted':计算每个类别的 precision,而后返回其加权均值,权重为每个类别的样本数。'samples':计算每个样本的 precision,而后返回其均值。该办法仅仅对于多标签分类问题有意义。None:计算每个类别的 precision,而后以数组的模式返回每个 precision。sample_weight:样本权重,默认每个样本的权重为 1
# 办法封装
def calc_precision_score(y_true: list, y_pred: list, labels=MY_CLASSES, average=None, verbose=False):
    res = precision_score(y_true, y_pred, labels=labels, average=average)
    if verbose:
        print("precision:%s" % res)

    return res

召回率(查全率,Recall)

召回率(Recall)又叫查全率,它是针对原样本而言的,它的含意是在理论为正的样本中被预测为正样本的概率,其公式如下:

Recall = TP/(TP+FN)

毛病:都预测为正例时也会笼罩所有实在的正例,召回率也为 100%。

召回率的利用场景:比方拿网贷守约率为例,绝对好用户,咱们更关怀坏用户,不能错放过任何一个坏用户。因为如果咱们过多的将坏用户当成好用户,这样后续可能产生的违约金额会远超过好用户偿还的借贷利息金额,造成重大偿失。召回率越高,代表理论坏用户被预测进去的概率越高,它的含意相似:宁肯错杀一千,绝不放过一个。

sklearn 实现:

from sklearn.metrics import recall_score

sklearn.metrics.recall_score(y_true, y_pred, labels=None,
pos_label=1,average='binary', sample_weight=None)
返回值:查全率。即实在的正类中,有多少比例被预测为正类。参数:参考 precision_score。# 办法封装
def calc_recall_score(y_true: list, y_pred: list, labels=MY_CLASSES, average=None, verbose=False):
    res = recall_score(y_true, y_pred, labels=labels, average=average)
    if verbose:
        print("recall: %s" % res)

    return res

下图正准确率和召回率做了进一步阐明

PR 曲线

通过准确率和召回率的公式可知:精准率和召回率的分子是雷同,都是 TP,但分母是不同的,一个是(TP+FP),一个是(TP+FN)。两者的关系能够用一个 P - R 图来展现:

分类模型的最初输入往往是一个概率值,咱们个别须要把概率值转换为具体的类别,对于二分类来说,咱们设置一个阈值(threshold),而后大于此阈值断定为正类,反之负类。上述评估指标(Accuracy、Precision、Recall)都是针对某个特定阈值来说的,那么当不同模型取不同阈值时,如何全面的评估不同模型?因而这里须要引入 PR 曲线,即 Precision-Recall 曲线来进行评估。

为了找到一个最合适的阈值满足咱们的要求,咱们就必须遍历 0 到 1 之间所有的阈值,而每个阈值下都对应着一对查准率和查全率,从而咱们就失去了这条曲线。

如下图所示,纵坐标是准确率 P,横坐标是召回率 R。对于一个模型来说,
其 P - R 曲线上的一个点代表着,在某一阈值下,模型将大于该阈值的后果断定为正样本,小于该阈值的后果断定为负样本,
此时返回后果对应一对儿召回率和准确率,作为 PR 坐标系上的一个坐标。
整条 P - R 曲线是通过将阈值从高到低挪动而生成的。P- R 曲线越凑近右上角(1,1)代表模型越好。在事实场景,须要依据不同决策要求综合判断不同模型的好坏。

评估规范:

先看平滑不平滑(越平滑越好)。一般来说,在同一测试集,下面的比上面的好(绿线比红线好)。当 P 和 R 的值靠近时 F1 值最大。此时画连贯(0,0)和(1,1)的线。线和 PR 曲线重合的中央 F1 值最大。此时的 F1 对于 PR 曲线就相当于 AUC 对于 ROC 一样。

PR 曲线下的面积称为 AP(Average
Precision),示意召回率从 0 - 1 的均匀精度值。AP 可用积分进行计算。AP 面积不会大于 1。PR 曲线下的面积越大,模型性能越好。

所谓性能优的模型应该是在召回率增长的同时放弃精确度在一个较高水平。

sklearn 实现:

sklearn.metrics.precision_recall_curve(y_true, probas_pred, pos_label=None,
sample_weight=None)

返回值:一个元组,元组内的元素别离为:P- R 曲线的查准率序列。该序列是递增序列,序列第 i 个元素是当正类概率的断定阈值为
thresholds[i]时的查准率。P- R 曲线的查全率序列。该序列是递加序列,序列第 i 个元素是当正类概率的断定阈值为
thresholds[i]时的查全率。P- R 曲线的阈值序列 thresholds。该序列是一个递增序列,给出了断定为正例时的正类概率的阈值。参数:y_true:实在的标记汇合。probas_pred:每个样本预测为正类的概率的汇合。pos_label:正类的类别标记。sample_weight:样本权重,默认每个样本的权重为 1。def calc_precision_recall_curve(class_info, class_name=None, show=True, save=False, verbose=False):
    """
    计算 PR 曲线
    :param class_info: 
    :param class_name: 
    :param show: 
    :param save: 
    :param verbose: 
    :return: 
    """precision, recall, thresholds = precision_recall_curve(class_info['gt_lbl'], class_info['score'])
    if verbose:
        print("%s precision:%s" % (class_name, precision,))
        print("%s recall:%s" % (class_name, recall,))
        print("%s thresholds:%s" % (class_name, thresholds,))

    if show:
        show_PR_curve(recall, precision, class_name)

    return precision, recall, thresholds

PR 曲线绘制办法:

def show_PR_curve(recall, precision, class_name=None, save=False):
    """
    绘制 PR 曲线
    :param recall:
    :param precision:
    :param class_name:
    :param save:
    :return:
    """plt.figure("%s P-R Curve" % class_name)
    plt.title('%s Precision/Recall Curve' % class_name)
    plt.xlabel('Recall')
    plt.ylabel('Precision')

    plt.plot(recall, precision)
    if save:
        plt.savefig("./%s_pr_curve.png")
    plt.show()

F1 score 和谐平均值

F1
Score 又称 F -Measure,是准确率和召回率的和谐值,更靠近于两个数较小的那个,所以准确率和召回率靠近时 F1 值最大。很多举荐零碎的评测指标就是用 F1
Score。

Precision 和 Recall 是既矛盾又对立的两个指标,为了进步 Precision 值,
分类器须要尽量在“更有把握”时才把样本预测为正样本,
但此时往往会因为过于激进而漏掉很多“没有把握”的正样本,
导致 Recall 值升高。那么当不同模型的 Recall 和 Precision 各有劣势时该如何抉择模型?如果想要找到二者之间的一个平衡点,咱们就须要一个新的指标:F1 分数。F1 分数同时思考了查准率和查全率,让二者同时达到最高,取一个均衡。F1 分数的公式为
= 2 查准率 查全率 / (查准率 +
查全率)。咱们在 PR 曲线图 1 中看到的平衡点就是 F1 分数得来的后果。

在事实场景,如果两个模型,一个 precision 特地高,recall 特地低,另一个 recall 特地高,precision 特地低的时候,f1-score 可能是差不多的,可能不能通过一个 f1
socre 做出最终判断,此时就须要依据不同场景抉择其余适合的指标做出评判。

sklearn 实现:

from sklearn.metrics import f1_score #和谐平均值 F1

f1_score(y_true, y_pred, labels=None, pos_label=1, average='binary',
sample_weight=None)

返回值:值。即查准率和查全率的和谐均值。参数:参考 precision_score。#办法封装
def calc_f1_score(y_true: list, y_pred: list, labels=MY_CLASSES, average=None, verbose=False):
    res = f1_score(y_true, y_pred, labels=labels, average=average)
    if verbose:
        print("f1_score: %s" % res)

    return res

ROC 曲线

ROC(Receiver Operating
Characteristic- 受试者工作特色曲线,又称感受性曲线),用图形来形容二分类模型的性能体现,是一个全面评估模型的指标。

ROC 和 AUC 能够忽视样本不均衡的起因是:灵敏度和(1- 特异度),也叫做真正率(TPR)和假正率(FPR)。因为 TPR 和 FPR 别离是基于理论体现 1 和 0 登程的,也就是说它们别离在理论的正样本和负样本中来察看相干概率问题。正因为如此,所以无论样本是否均衡,都不会被影响。

例如:总样本中,90% 是正样本,10% 是负样本。咱们晓得用准确率是有水分的,然而用 TPR 和 FPR 不一样。这里,TPR 只关注 90% 正样本中有多少是被真正笼罩的,而与那 10% 毫无关系,同理,FPR 只关注 10% 负样本中有多少是被谬误笼罩的,也与那 90% 毫无关系,所以能够看出:如果咱们从理论体现的各个后果角度登程,就能够防止样本不均衡的问题了,这也是为什么选用 TPR 和 FPR 作为 ROC/AUC 的指标的起因。

X 轴:假正率(FPR),模型预测为假的正例在实在负例的占比。错误判断的正类占所有负类的比例,医学上等价于误诊率。

Y 轴:真正率(TPR),模型预测为真的正例在实在正例的占比。

ROC 曲线离对角线越近,模型的准确率越低。

曲线阐明:

ROC 曲线是通过不同阈值下的 FPR 和 TPR 坐标所失去的。具体来说,通过动静地调整模型概率阈值(概率阈值的意思是模型多大概率断定为正类),
从最高的值开始(比方 1,对应着 ROC 曲线的零点),逐步调整到最低概率值,
每一个概率值都会对应一个 FPR 和 TPR,在 ROC 图上绘制出每个概率值对应的地位,
再连贯所有点就失去最终的 ROC 曲线。

曲线特色:

  • 通过调整判断分类的阈值(逻辑回归默认阈值 0.5),TPR 和 FPR 随之扭转,进而在 ROC 曲线坐标上造成多个点,反馈模型分类成果。
  • TPR 增长越快,同时 FPR 越低,曲线越凸,模型的分类性能越好,即预测为正确的正例越多。
  • ROC 曲线比过 (0,0), (1,0) 两点。起因:

逻辑回归模型默认阈值为 0.5,sigmoid()后果即类别概率 p 默认≥0.5 时,模型预测为类别 1(正例)。那么批改阈值为 0 时,p≥0 模型预测为类别 1(正例),阐明该模型该阈值下会将所有数据均预测为类别 1(无论对错),此时 FN=TN= 0 个,TPR=FPR=1

批改阈值为 1 时,p≥1 模型预测为类别 1(正例),p 是不可能大于 100% 的,阐明该模型该阈值下会将所有数据均预测为类别 0(无论对错),此时 FP=TP= 0 个,TPR=FPR=0

sklearn 实现:

roc_curve 函数用于计算分类后果的 ROC 曲线。其原型为:sklearn.metrics.roc_curve(y_true, y_score, pos_label=None, sample_weight=None,
drop_intermediate=True)

返回值:一个元组,元组内的元素别离为:ROC 曲线的 FPR 序列。该序列是递增序列,序列第 i 个元素是当正类概率的断定阈值为
thresholds[i]时的假正例率。ROC 曲线的 TPR 序列。该序列是递增序列,序列第 i 个元素是当正类概率的断定阈值为
thresholds[i]时的真正例率。ROC 曲线的阈值序列 thresholds。该序列是一个递加序列,给出了断定为正例时的正类概率的阈值。参数:y_true:实在的标记汇合。y_score:每个样本预测为正类的概率的汇合。pos_label:正类的类别标记。sample_weight:样本权重,默认每个样本的权重为 1。drop_intermediate:一个布尔值。如果为 True,则摈弃某些不可能呈现在 ROC 曲线上的阈值。#办法封装
def calc_roc_curve(class_info, class_name=None, show=True, save=False, verbose=False):
    """
    计算 roc 曲线
    :param class_info: 
    :param class_name: 
    :param show: 
    :param save: 
    :param verbose: 
    :return: 
    """fpr, tpr, thresholds = roc_curve(class_info['gt_lbl'], class_info['score'], drop_intermediate=True)
    if verbose:
        print("%s fpr:%s" % (class_name, fpr,))
        print("%s tpr:%s" % (class_name, tpr,))
        print("%s thresholds:%s" % (class_name, thresholds,))

    if show:
        auc_score = calc_auc_score(fpr, tpr)
        show_roc_curve(fpr, tpr, auc_score, class_name)

    return fpr, tpr, thresholds

ROC 曲线绘制办法:

def show_roc_curve(fpr, tpr, auc_score, class_name=None, save=False):
    plt.figure("%s ROC Curve" % class_name)
    plt.title('%s ROC Curve' % class_name)
    plt.xlabel('False Positive Rate')  # 横坐标是 fpr
    plt.ylabel('True Positive Rate')  # 纵坐标是 tpr

    plt.plot(fpr, tpr, 'b', label='AUC = %0.2f' % auc_score)
    plt.legend(loc='lower right')
    plt.plot([0, 1], [0, 1], 'r--')
    plt.xlim([-0.1, 1.1])
    plt.ylim([-0.1, 1.1])
    if save:
        plt.savefig("./%s_auc_curve.png")
    plt.show()

AUC(ROC 曲线的面积)

AUC (Area Under Curve
被定义为 ROC 曲线下的面积,显然这个面积的数值不会大于 1。又因为 ROC 曲线个别都处于 y = x 这条直线的上方,所以 AUC 的取值范畴个别在 0.5 和 1 之间。应用 AUC 值作为评估规范是因为很多时候 ROC 曲线并不能清晰的阐明哪个分类器的成果更好,而作为一个数值,对应 AUC 更大的分类器成果更好。

sklearn 实现:

roc_auc_score 函数用于计算分类后果的 ROC 曲线的面积 AUC。其原型为:sklearn.metrics.roc_auc_score(y_true, y_score, average='macro',
sample_weight=None)

返回值:AUC 值。参数:参考 roc_curve。#也能够通过如下办法计算失去
def calc_auc_score(fpr, tpr, verbose=False):
    res = auc(fpr, tpr)
    if verbose:
        print("auc:%s" % res)

    return res

AUC 的计算有两种形式:梯形法和 ROC
AUCH 法,都是以迫近法求近似值,具体见 wikipedia。

从 AUC 判断分类器(预测模型)优劣的规范:

  • AUC =
    1,是完满分类器,采纳这个预测模型时,存在至多一个阈值能得出完满预测。绝大多数预测的场合,不存在完满分类器。
    -5 < AUC <
    1,优于随机猜想。这个分类器(模型)妥善设定阈值的话,能有预测价值。
  • AUC = 0.5,跟随机猜想一样(例:丢铜板),模型没有预测价值。
  • AUC < 0.5,比随机猜想还差;但只有总是反预测而行,就优于随机猜想。

三种 AUC 值示例:

简略说:AUC 值越大的分类器,正确率越高。

注:TPR、FPR、Precision、Recall 的定义来比照,TPR、Recall 的分母为样本中正类的个数,FPR 的分母为样本中负类的个数,样本一旦确定分母即为定值,因而三个指标的变动随分子减少枯燥递增。然而 Precision 的分母为预测为正类的个数,会随着阈值的变动而变动,因而 Precision 的变动受 TP 和 FP 的综合影响,不枯燥,变动状况不可预测。

多类别状况下 ROC-AUC 曲线绘制办法

def show_roc_info(classdict, show=True, save=False, figsize=(30, 22), fontsize=12):
    """
    多类别状况下计算展现每个类别的 roc-auc 图
    :param classdict: 
    :param show: 
    :param save: 
    :param figsize: 
    :param fontsize: 
    :return: 
    """
    def sub_curve(fpr, tpr, auc_score, class_name, sub_idx):
        plt.subplot(6, 5, sub_idx)
        plt.title('%s ROC Curve' % class_name)
        plt.xlabel('False Positive Rate')  # 横坐标是 fpr
        plt.ylabel('True Positive Rate')  # 纵坐标是 tpr

        plt.plot(fpr, tpr, 'b', label='AUC = %0.2f' % auc_score)
        plt.legend(loc='lower right')
        plt.plot([0, 1], [0, 1], 'r--')
        plt.xlim([-0.1, 1.1])
        plt.ylim([-0.1, 1.1])

    if show:
        plt.figure("Maoyan video class AUC Curve", figsize=figsize)
        plt.subplots_adjust(bottom=0.02, right=0.98, top=0.98)
    for idx, cls in enumerate(MY_CLASSES):
        if cls in classdict:
            fpr, tpr, thresholds = calc_roc_curve(classdict[cls], class_name=cls, show=False)
            auc_score = calc_auc_score(fpr, tpr)
            print("%s auc:\t\t\t%.4f" % (cls, auc_score))
            if show:
                sub_curve(fpr, tpr, auc_score, cls, idx + 1)
        else:
            print("%s auc:\t\t\t0" % cls)
            sub_curve([0], [0], 0, cls, idx + 1)

    if save:
        plt.savefig("./maoyan_all_auc_curve.png")
    if show:
        plt.show()

理论应用技巧

对于 ROC,一般来说,如果 ROC 是润滑的,那么根本能够判断没有太大的 overfitting(比方图中 0.2 到 0.4 可能就有问题,然而样本太少了),这个时候调模型能够只看 AUC,面积越大个别认为模型越好。

对于 PRC(precision recall
curve)和 ROC 一样,先看平滑不平滑(蓝线显著好些),再看谁上谁下(同一测试集上),一般来说,下面的比上面的好(绿线比红线好)。当 P 和 R 越靠近 F1 就越大,个别连贯 (0,0) 和(1,1)的线和 PRC 重合的中央的 F1 是这条线最大的 F1(润滑的状况下),此时的 F1 对于 PRC 就好象 AUC 对于 ROC 一样。一个数字比一条线更不便调模型。

AP

严格的 AP 就是 PR 曲线下的面积,mAP 就是所有类 AP 的算术平均。
然而个别都是用迫近的办法去预计这个面积。

sklearn 实现:

sklearn.metrics.average_precision_score(y_true, y_score, average=‘macro’,
sample_weight=None)

留神:此实现仅限于二进制分类工作或多标签分类工作。参数:y_true : array, shape = [n_samples] or [n_samples, n_classes]
实在标签:取 0 和 1

y_score : array, shape = [n_samples] or [n_samples, n_classes]

预测标签:[0,1]之间的值。能够是正类的概率预计、相信值,也能够是决策的非阈值度量(如某些分类器上的“决策函数”返回的)average : string, [None,‘micro’,‘macro’(default),‘samples’,‘weighted’]
sample_weight : array-like of shape = [n_samples], optional sample weights.

#办法封装
def calc_AP_score(class_info, class_name=None, average="macro", verbose=True):
    res = average_precision_score(class_info['gt_lbl'], class_info['score'], average=average)
    if verbose:
        print("%s ap:\t\t\t%.4f" % (class_name, res))

    return res

AP 计算方法

首先用训练好的模型失去所有测试样本的 confidence
score,假如某类共有 20 个测试样本,每个的 id,confidence score 和 ground truth
label 如下:

接着对 confidence score 排序失去:

计算出 TopN 对应 Recall 和 precision。其中,对于某个 recall 值 r,precision 值取所有 recall

=r 中的最大值(这样保障了 p - r 曲线是枯燥递加的,防止曲线呈现摇晃)这种办法叫做 all-points-interpolation。这个 AP 值也就是 PR 曲线下的面积值。

例如:top5 的 recall=2/6, precision=2/5=0.4, 当 recall>=2/ 6 时 precision 最大为 1。

top6 的 recall=3/6, precision=3/6, 在所有 recall>=3/ 6 时 precision 最大为 4 /7。

此时

AP=1*(1/6) + 1*(1/6)+ (4/7)*(1/6) + (4/7)*(1/6) + (5/11)*(1/6) + (6/16)*
(1/6) = 0.6621

相应的 Precision-Recall 曲线(这条曲线是枯燥递加的)如下:​

mAP

mean Average Precision, 即各类别 AP 的平均值

用上述办法别离算出各个类的 AP,而后取均匀,就失去 mAP 了。mAP 的益处是能够避免 AP
bias 到某一个数量较多的类别下来。

sklearn 实现:

#mAP 计算封装
def calc_mAP_score(classdict, verbose=True):
    AP = []
    for cls in MY_CLASSES:
        if cls in classdict:
            AP.append(calc_AP_score(classdict[cls], cls))
        else:
            print("%s ap:\t 0" % cls)
            AP.append(0)
    mAP_score = np.mean(AP)
    if verbose:
        print("mAP:%s" % mAP_score)
    return mAP_score

多类别状况下计算展现每个类别的 pr 图及对应的 AP 值

def show_mAP_info(classdict, show=True, save=False, figsize=(30, 22), fontsize=12):
    """
    多类别状况下计算展现每个类别的 pr 图及对应的 AP 值
    :param classdict:
    :param show:
    :param save:
    :param figsize:
    :param fontsize:
    :return:
    """

    def sub_curve(recall, precision, class_name, ap_score, sub_idx):
        plt.subplot(6, 5, sub_idx)
        plt.title('%s PR Curve, ap:%.4f' % (class_name, ap_score))
        plt.xlabel('Recall')
        plt.ylabel('Precision')
        plt.plot(recall, precision)

    AP = []
    if show:
        plt.figure("Maoyan video class P-R Curve", figsize=figsize)
        plt.subplots_adjust(bottom=0.02, right=0.98, top=0.98)
    for idx, cls in enumerate(MY_CLASSES):
        if cls in classdict:
            ap_score = calc_AP_score(classdict[cls], cls)
            precision, recall, thresholds = calc_precision_recall_curve(classdict[cls], class_name=cls, show=False)
            if show:
                sub_curve(recall, precision, cls, ap_score, idx + 1)
        else:
            ap_score = 0
            print("%s ap:\t\t\t0" % cls)
            sub_curve([0], [0], cls, ap_score, idx + 1)

        AP.append(ap_score)
    if save:
        plt.savefig("./maoyan_all_ap_curve.png")
    if show:
        plt.show()

    mAP_score = np.mean(AP)
    print("mAP:%s" % mAP_score)
    return mAP_score

多类别状况下获取所需标签信息的办法

def get_simple_result(df: DataFrame):
    y_true = []
    y_pred = []
    pred_scores = []
    for idx, row in df.iterrows():
        video_path = row['video_path']
        gt_label = video_path.split("/")[-2]
        y_true.append(gt_label)

        pred_label = row['cls1']
        y_pred.append(pred_label)

        pred_score = row['score1']
        pred_scores.append(pred_score)

    return y_true, y_pred, pred_scores
def get_multiclass_result(df: DataFrame):
    classdict = {}
    for idx, row in df.iterrows():
        video_path = row['video_path']
        gt_label = video_path.split("/")[-2]
        pred_label = row['cls1']
        pred_score = row['score1']
        if pred_label in classdict:
            classdict[pred_label]['score'].append(pred_score)
            classdict[pred_label]['gt_lbl'].append(1 if gt_label == pred_label else 0)
        else:
            classdict[pred_label] = {'score': [pred_score], 'gt_lbl': [1 if gt_label == pred_label else 0]}
    return classdict

对数损失(log_loss)

from sklearn.metrics import log_loss
log_loss(y_true,y_pred)

分类指标的文本报告(classification_report)

classification_report 函数用于显示次要分类指标的文本报告。在报告中显示每个类的精确度,召回率,F1 值等信息。

sklearn 实现:

sklearn.metrics.classification_report(y_true, y_pred, labels=None,
target_names=None, sample_weight=None, digits=2)

返回值:一个格式化的字符串,给出了分类评估报告。参数:y_true:实在的标记汇合。y_pred:预测的标记汇合。labels:一个列表,指定报告中呈现哪些类别。target_names:一个列表,指定报告中类别对应的显示进去的名字。digits:用于格式化报告中的浮点数,保留几位小数。sample_weight:样本权重,默认每个样本的权重为 1
分类评估报告的内容如下,其中:precision 列:给出了查准率。它顺次将类别 0 作为正类,类别 1 作为正类...
recall 列:给出了查全率。它顺次将类别 0 作为正类,类别 1 作为正类...
F1 列:给出了 F1 值。support 列:给出了该类有多少个样本。avg / total 行:对于 precision,recall,f1 给出了该列数据的算术平均。对于 support 列,给出了该列的算术和(其实就等于样本集总样本数量)。

应用总结

  • 对于分类模型,AUC、ROC 曲线(FPR 和 TPR 的点连成的线)、PR 曲线(准确率和召回率的点连成的线)是综合评估模型辨别能力和排序能力的指标,而准确率、召回率和 F1 值是在确定阈值之后计算失去的指标。
  • 对于同一模型,PRC 和 ROC 曲线都能够阐明肯定的问题,而且二者有肯定的相关性,如果想评测模型成果,也能够把两条曲线都画进去综合评估。
  • 对于有监督的二分类问题,在正负样本都足够的状况下,能够间接用 ROC 曲线、AUC 评估模型成果;而在样本极不平衡的状况下,PR 曲线更能反馈模型成果。
  • 在确定阈值过程中,能够依据 Precision、Recall 或者 F1 来评估模型的分类成果。对于多分类问题,能够对每一类别离计算 Precision、Recall 和 F1,综合作为模型评估指标。

    回归模型

    均匀绝对误差(MAE mean absolute error)

    sklearn 实现:

mean_absolute_error 函数用于计算回归预测误差绝对值的均值(mean absolute
error:MAE),其原型为:sklearn.metrics.mean_absolute_error(y_true, y_pred, sample_weight=None,
multioutput='uniform_average')

返回值:预测误差绝对值的均值。参数:y_true:实在的标记汇合。y_pred:预测的标记汇合。multioutput:指定对于多输入变量的回归问题的误差类型。能够为:'raw_values':对每个输入变量,计算其误差。'uniform_average':计算其所有输入变量的误差的平均值。sample_weight:样本权重,默认每个样本的权重为 1。

均方误差(MSE mean squared error)

mean_squared_error 函数用于计算回归预测误差平方的均值(mean square
error:MSE),其原型为:

sklearn.metrics.mean_squared_error(y_true, y_pred, sample_weight=None,

multioutput='uniform_average')

返回值:预测误差的平方的平均值。参数:参考 mean_absolute_error。

均方根误差(RMSE root mean squared error)

归一化均方根误差(NRMSE normalized root mean squared error)归一化均方根误差

决定系数(R2)

R2 是多元回归中的回归平方和占总平方和的比例, 它是度量多元回归方程中拟合水平的一个统计量, 反映了在因变量 y 的变差中被预计的回归方程所解释的比例。

R2 越靠近 1, 表明回归平方和占总平方和的比例越大, 回归线与各观测点越靠近, 用 x 的变动来解释 y 值变差的局部就越多, 回归的拟合水平就越好。

from sklearn.metrics import r2_score

r2_score(y_true, y_pred, sample_weight=None, multioutput='uniform_average')

参考以下文章,本人总结的深度学习罕用评估指标:
Terry:https://zhuanlan.zhihu.com/p/…
cicada:https://zhuanlan.zhihu.com/p/…
https://www.pythonf.cn/read/1…
路远:https://www.zhihu.com/questio…

点击关注,第一工夫理解华为云陈腐技术~

正文完
 0