【全面总结】model.compile方法中metrics评价函数

关于model.compile方法中metrics评价函数的总结

问题引入

  大家会发现我们在做实验的过程中,经常会发现在Model.compile的过程中会需要写一个参数比如:metrics=['accuracy'],那么这个时候一般情况下很少有文章或者代码注释中会提及这个参数选择的原因或者意义,尤其是笔者前期是个小白,一开始接连做的都是几个二分类的神经网络实验,甚至一度以为只要一直写metrics=['accuracy']就不会报什么错。但这种想法其实是错误且荒谬的,这个参数其实在面对不同的数据集和问题的时候有着不同的选择和作用。

简单解释评价函数

  首先,这个参数的意义是定义评价函数,什么是评价函数呢,跑过模型的同学肯定都知道,在打印结果的时候你会看到每个epoch的acc和loss,其中acc和val_acc就是通过定义评价函数得到的,简而言之,评价函数的选择直接决定了你得到的准确度表达。

评价函数的种类(合理举例辅助理解)

  所以说对不同的问题选择使用什么样的评价函数将决定了你最终的训练集得分,还是十分重要的,而且在调参过程中,有的小伙伴不喜欢看loss,而喜欢看验证集得分val_acc那你也需要好好来了解一下评价函数的分类。

  事实上Keras当中为我们定义了6种不同的accuracy,最常用的就是我刚刚举例的accuracy,现在我们再举一个更精确的例子:

  accuracy真实标签和模型预测均为标量,如果真实标签序列为[1, 1, 3, 0, 2, 5],预测序列为[1, 2, 3, 1, 2, 5],此时可以看到命中了四个,则[accuracy] = 4/6 = 0.6667。

  另外一种比较常见的评价函数是binary_accuracy,这种评价函数适用于二分类问题的处理。首先样本集合应该有真实标签序列,如[0, 1, 1, 0],模型预测为概率序列,如[0.6, 0.7, 0.6, 0.9],但是现在我们只有概率序列该怎么和标签序列比较呢,该评价函数有一个threshold参数,参数的默认值为0.5。预测序列中概率 > threshold的设为1,< = threshold的设为0。所以模型预测会由[0.3, 0.7, 0.6, 0.9]转换为[0, 1, 1, 1],然后再第一种accuracy计算方法(命中了3/4,所以accuracy = 3/4 = 0.7500)。

  当面对多分类问题或者多标签的任务时,评价函数通常可能会用到categorical_accuracy和 sparse_categorical_accuracy两个函数。

  首先是categorical_accuracy,首先真实值和预测值都是一个one-hot向量,这个评价函数的策略是比较两个向量中最大元素的下标index值是否一致注意,这里只比较一个值,即最大的那个值的index,这对于多分类单标签任务的是合适的,但并不适用于多标签任务。举个例子来说就好比真实值为[0, 0, 3, 1]而预测值为[0.2, 0.1, 0.9, 0.5]则视为预测准确。

  而sparse_categorical_accuracy中真实值本身已经是下标index,而预测值仍然是个向量,比较真实值的下标值所对应的预测序列中的值是否为整个序列中最大的,如果是,则视为预测精准。比如真实值为2(注意下标从0开始),预测序列为[0.1, 0.38, 0.79, 0.5],评价结果视为预测准确。

  下面两种评价函数要好好理解,二者核心思想其实就是:排名前k个预测序列元素下标能否包含真实值序列最大值的下标的评分函数。这句话听完很抽象,没关系我们慢慢举例。

  首先看top_k_categorical_accuracy它相当于在categorical_accuracy的基础上加上top_k之后自然考虑的不再是单一序列下标号的比较。categorical_accuracy要求样本在真值类别上的预测分数是在所有类别上预测分数的最大值,才算预测对。而top_k_categorical_accuracy只要求样本在真值类别上的预测分数排在其在所有类别上的预测分数的前k名就行

  举一个详细的例子:比如有5个样本,其真实值为[[0, 1, 0], [0, 0, 1], [0, 1, 0], [0, 1, 0], [1, 0, 0]],预测序列为[[0.8, 0.2, 0.1], [0.3, 0.6, 0.1], [0.5, 0.4, 0.1], [0.3, 0.6, 0.1], [0.9, 0, 0.1]],根据前面知识我们可以计算得到其categorical_accuracy=40%,但是如果你选择的评价函数是top_k_categorical_accuracy答案就完全不一样了,可以这么说,top_k有着更宽松的约束,因为相当于允许最大值只需要排进前k就算预测对了。当然这也就意味着预测准确与否跟k的取值息息相关。比如刚才这个例子,如果k取值 > = 3,其top_k_categorical_accuracy是100%,是因为每个向量里总共就3个类别,最大值肯定位于前3之内,那就是百分之百准确了没有意义。所以设置k值小于向量元素长度3才有意义,比如如果我们设置k = 2,那么top_k_ accuracy=75%。具体计算方法为:1)首先,将真值序列转为非onehot的形式,即[1, 2, 1, 1, 0](就是取出最大值的下标index组成新的向量)2)计算预测值的top_k的label,比如k=2时,预测值的序列可以转化为 = [[0, 1], [0, 1], [0, 1], [0, 1], [0, 2]](即找到预测序列中前两个比较大的值所对应的下标Index)3)根据每个样本的真实标签是否在预测标签的top_k内来统计准确率,上述5个样本为例,1在[0, 1]内,2不在[0, 1]内,1在[0, 1]内,1在[0, 1]内,0在[0, 2]内,5个样本总共预测对了4个,因此k=2时top_k_categorical_accuracy=80%。注意在使用的过程中Keras默认的k值取为5,所以如果在调用时如果使用默认值,需要确保分类个数>5才行否则将出现命中率100%的情况。

  sparse_top_k_categorical_accuracy与top_k_categorical_accurac也是一样的思路,只不过sparse_top_k真值不是onehot的形式。(类比刚才多分类的两个评分函数的区别来理解会有所帮助)

  假设给定4个样本,其真值序列为[2, 1, 2, 2],预测序列为[[0.2, 0.5, 0.15], [0.5, 0.3, 0.1], [0.3, 0.7, 0.2], [0.9, 0.05, 0.4]]。计算sparse_top_k_categorical_accuracy的命中率应该按照如下方法:首先假设选择k=2,则先将预测序列转化成[[0, 1], [0, 1], [0, 1], [0, 2]],我们可以通过刚才的方法来逐个查看,2不在[0, 1]中,1在[0, 1]中,2不在[0, 1]中,2在[0, 2]中。所以4个样本命中了2个,命中率为50%。

  其实可以发现当两种top_k方法中当你把k设置为1时,top_k_categorical_accuracy和sparse_top_k_categorical_accuracy方法会由于k值太小而退化为前两种categorical_accuracy以及sparse_categorical_accuracy方法。

总结使用场景

  根据刚才我们介绍的原理,大家应该对6种不同的评价函数有了很好的理解。根据不同评价函数使用的特点,在此给出总结。当然首先值得一提的是keras中的accuracy metric用法很多,大家可以根据自己的实际情况选择合适的accuracy metric,我们在这里讨论的只是比较常见的几种方法。

  1) 如果真实值标签和预测值都是具体的index值(如真值序列 = [1, 1, 1], y_pred=[0, 1, 1])时,直接使用accuracy评价函数就可以满足大部分情况。(即非常简单的应用场景,数据集当中有明确的分类信息label)

  2) 如果真实值标签是具体的index值,而预测值是向量形式,且问题为多分类问题(如真实值= [1, 1, 1], 预测序列=[[0.2, 0.3, 0.5], [0.45, 0.2, 0.35], [0, 0.24, 0.78]])时,用sparse_categorical_accuracy评价函数可以解决问题。

  3)如果真实值标签是one-hot形式,而预测值是向量形式(如真实值 = [[0, 1, 0], [0, 0, 1], [1, 0, 0]], 预测值= [[0.52, 0.33, 0.15], [0.9, 0.1, 0], [0, 0.4, 0.6]])时,用categorical_accuracy评价函数就可以。

  目前,由于所做的实验有限,所以理解也只是基于一个比较浅层的水平,本文主要目的还是为了帮助大家理解每种评价函数的原理。希望能够有所帮助,当然笔者也是站在巨人的肩膀上学习,总结本篇用法,参考自三位大佬的博客:

  https://blog.csdn.net/qq_36588760/article/details/105689736

  https://blog.csdn.net/weixin_44866160/article/details/106437277

  https://blog.csdn.net/qq_20011607/article/details/89213908

       学无止境,向前辈致敬,希望大家一起加油。

你可能感兴趣的:(Tensorflow学习,深度学习,深度学习,算法,人工智能,python)