以前在研究Object Detection的时候,只是知道Precision这个指标,可是mAP(mean Average Precision)具体是如何计算的,暂时还不知道。最近作OD的任务迫在眉睫,因此仔细的研究了一下mAP的计算。其实说实话,mAP的计算,自己有不少现成的代码可供调用了,公式也写的很清楚,可是我认为仔细的研究清楚其中的原理更重要。html
AP这个概念,其实主要是在信息检索领域(information retrieval)中的概念,因此这里会比较快速的过一下这个在信息检索领域是如何起做用的。python
Precision其实就是在识别出来的图片中,True positives所占的比率:
其中的n表明的是(True positives + False positives),也就是系统一共识别出来多少照片 。
网络
Recall 是被正确识别出来的个数与测试集中全部的个数的比值:
Recall的分母是(True positives + False negatives),这两个值的和,能够理解为一共有多少张飞机的照片。 app
以下图所示,假如一个用户向系统提交一个查询(例如“什么是猫”),系统返回了一系列查询的结果,这些结果是系统根据用户提交的信息,断定出来系统内全部跟这个信息有关的结果。ide
在这个结果里,黄色的部分是系统返回的结果,绿色的部分是总共对用户有用的结果。二者的交集,也就是中间的地方,一般叫作True Positive(TP),中文译名是真阳。而返回结果的剩下的部分,则是False Positive。也就是假阳,意思就是说这些自己是对用户没啥用的,可是系统断定这些对用户有用而且提交给用户了,因此叫“假阳”。而绿色部分剩下的,False Negative,假阴,则是原本对用户有用的结果,可是被系统断定没用,“假阴”。剩下的灰色地方则是True Negative,“真阴”,就是真的没啥用的结果。函数
Precision是提交给用户的结果里边,究竟有多少是对的,或者反过来讲,咱们给了用户多少没用的垃圾。Recall是一共有这么多的有用结果,系统究竟能断定出来多少是有用的(可以检出多少?),或者反过来讲,咱们究竟丢了多少有用的。这两个数是成对出现,单独出现没有意义。为何这么说?一个例子是我能够轻轻松松将recall提升到100%,那就是无论用户查询啥,我都把系统内全部的文档都给他,这样确定没丢东西,可是用户也无法获得的好的结果。性能
准确率,也就是accuracy,测试
是系统究竟作对了多少。若是是对于平衡样原本说,这个没问题。可是对于样本不平衡的状况,这就不行。例如信息检索,有99.999%的信息都对用户没用,并且大部分系统确定都能判别出来这些没用,因此对于绝大部分系统,准确率都是99.999%,这个就不能很好的衡量系统性能了。再好比一个90个正样本,10个负样本数据,若是所有分类为正则准确率为90%,这样评价不能客观反映分类器对不平衡数据的性能。spa
可是咱们仍是但愿有一个数可以衡量系统的性能,不然系统A的precision比系统B高,可是recall却比系统B低,那么咱们就不太好选了。因此综合Precision和Recall,咱们获得一个F Score:.net
这个F Score是P和R的调和平均数(harmonic mean),β的做用是代表P与R谁比较重要。harmonic mean有个特色,就是假如其中一个P或者R比较小,那么总体就会很小,也就是对两个数中若是有特别小的数的惩罚(penalty)比较大。这是代数平均数所没有的特性。通常来讲,会把β设置成1,这个时候就成为F1 Score。几何表达以下图所示。
用户提交一个检索Query,获得的结果实际上是一个列表,也就是一个有序表,这个表里饱含着全部检索的结果。这个表的序,其实也反映了系统的性能。若是系统把有用的信息排到特别后边,把没用的信息放到前边,也是一个比较性能差的系统。对于一个ranking,咱们如何评估它的性能呢?
如上图所示,假设对于已经排好序的检测结果:
咱们首先在每个元素上都计算一下precision和recall。计算的方法是:对于第N个元素的precision和recall,计算前N个元素的recall和precision。
举例说明:对于Ranking #1,第一个元素,前1个元素也就是这个元素了,它的recall是1/6=0.17,由于检出了1个,一共有6个须要检出的元素,而precision则是1/1=1,由于一共有1个元素,检出了1个元素,因此是1。
对于Ranking #1 第二个元素的precision和recall,则recall是1/6=0.17。第二个是错的,因此precision是1/2=0.5,由于一共有2个元素。那么对比Ranking #1和#2,咱们能够看到由于排序不一样,因此precision不同。这是由于这种计算方法会给靠前的元素比较大的bias。这样precision就能够衡量序在结果中的做用了。
如此咱们即可以画出Recall-Precision的关系,以及F1的结果。通常来讲,F1 Score会在Recall-Precision相交的地方达到最大值,可是这也不必定。毕竟这个极值其实仍是须要知足必定的条件的。可是总体趋势就如同右上的那个小图那样子。
P-R曲线
咱们把上一节计算出来的Recall和Precision画出来,获得以下图所示的结果:
这个曲线就比较蛋疼了。它压根不是一个函数。咱们想知道Query 1 Recall = 0.5的状况下,Precision是多少,这事儿彻底无法用普通的插值来弄。可是咱们知道的是,Precision-Recall的曲线,趋势是降低的,因此前人就提出一种差值方法:任给一个Recall值,它对应的Precision值就等于它最近的右侧的那个“有值”Precision值中最大的那个值。举个例子,例如那个黑色的线,当recall=0.3的时候,它对应的precision值就是0.3右侧最近的有值的,也就是recall=0.4的那个值,可是recall=0.4对应不少值,包括了0.7五、0.5和0.4,则选那个最大的0.75,以下图所示:
红色的线和蓝色的线就分别是Query 1和2的Interpolated Recall-precision plot。而后对于总体系统,就能够平均一下Q1和Q2的结果,获得一个平均性能。
有了这个插值完的曲线,咱们就能够对不一样系统进行一个性能分析,如上图所示。图中的结论都很简单明了。
到这里,mAP的定义其实就天然而然的明确了。Average Precision,就是对一个Query,计算其命中时的平均Precision,而mean则是在全部Query上去平均,例子以下图所示,一看就明了了。
回到咱们目标检测中的mAP,这个概念是PASCAL VOC比赛中所明确的metric。它的意思是输出的结果是一个ranked list,里边每个元素包含了类别、框的信息,以及confidence,这个confidence就用来排序。有了排序,就能够计算AP了,而后再针对全部分类,取一个mean,就获得了mAP。这里为什么要排序呢?是由于每个框有一个confidence,mAP做为评估指标,须要考虑confidence进来。比方说我给出一个框,说我有99%的信心这里有一个猫,结果这里没有,相比我给出一个框,说我有10%的信心这里有一个猫,结果也没有,这两个框的penalty和reward不能同样的。由于99%信心说有,结果没有,那就说明这个系统颇有问题。反之,假如我给出一个框,99%的信心说有一个猫,而后真有猫,相比10%信心说有猫,结果也是有猫,这两个框也不同。也就是越“靠谱”,reward越大。什么叫靠谱?靠谱的意思是信心足的时候,通常结果正确。因此咱们根据confidence进行排序以后,就应该给排名靠前的结果,也就是confidence比较大的一些更大的权重。因此才会有ranked list。或者能够理解为,我有一个query,查询的内容是,系统中的图片里猫都在那儿?那么这个就确定须要ranked list了。
值得一提的是在2010年以前,VOC比赛用的AP计算方法并非上边所述的计算方法,而是对interpolated 的那个图均匀取11个点,[0.0 0.1 0.2 … 1.0]而后求平均。后来才成上边所述的AP计算方法。
贴一段python的ap计算代码放在下边供参考:
def voc_ap(self, rec, prec, use_07_metric=True): if use_07_metric: ap = 0. # 2010年之前按recall等间隔取11个不一样点处的精度值作平均(0., 0.1, 0.2, …, 0.9, 1.0) for t in np.arange(0., 1.1, 0.1): if np.sum(rec >= t) == 0: p = 0 else: # 取最大值等价于2010之后先计算包络线的操做,保证precise非减 p = np.max(prec[rec >= t]) ap = ap + p / 11. else: # 2010年之后取全部不一样的recall对应的点处的精度值作平均 # first append sentinel values at the end mrec = np.concatenate(([0.], rec, [1.])) mpre = np.concatenate(([0.], prec, [0.])) # 计算包络线,从后往前取最大保证precise非减 for i in range(mpre.size - 1, 0, -1): mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i]) # 找出全部检测结果中recall不一样的点 i = np.where(mrec[1:] != mrec[:-1])[0] # and sum (\Delta recall) * prec # 用recall的间隔对精度做加权平均 ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1]) return ap
(受试者操做特征(Receiver Operating Characteristic),roc曲线上每一个点反映着对同一信号刺激的感觉性)
对于0,1两类分类问题,一些分类器获得的结果每每不是0,1这样的标签,如神经网络,获得诸如0.5,0,8这样的分类结果。这时,咱们人为取一个阈值,好比0.4,那么小于0.4的为0类,大于等于0.4的为1类,能够获得一个分类结果。一样,这个阈值咱们能够取0.1,0.2等等。取不一样的阈值,获得的最后的分类状况也就不一样。
以下面这幅图:
蓝色表示原始为负类分类获得的统计图,红色为正类获得的统计图。那么咱们取一条直线,直线左边分为负类,右边分为正,这条直线也就是咱们所取的阈值。
阈值不一样,能够获得不一样的结果,可是由分类器决定的统计图始终是不变的。这时候就须要一个独立于阈值,只与分类器有关的评价指标,来衡量特定分类器的好坏。
还有在类不平衡的状况下,如正样本90个,负样本10个,直接把全部样本分类为正样本,获得识别率为90%。但这显然是没有意义的。
如上就是ROC曲线的动机。
ROC空间将假正例率(False Positive Rate, 简称FPR)定义为 X轴,真正例率(True Positive Rate, 简称TPR)定义为 Y 轴。这两个值由上面四个值计算获得,公式以下:
TPR:在全部实际为正例的样本中,被正确地判断为正例之比率。
FPR:在全部实际为反例的样本中,被错误地判断为正例之比率。
咱们以FPR为横轴,TPR为纵轴,获得以下ROC空间。
咱们能够看出,左上角的点(TPR=1,FPR=0)(TPR=1,FPR=0),为完美分类。曲线距离左上角越近,证实分类器效果越好。点A(TPR>FPR)代表判断大致是正确的。中线上的点B(TPR=FPR)代表断定一半对一半错(这种最垃圾~~);下半平面的点C(TPR<FPR)说明断定大致错误。
如上,是三条ROC曲线,在0.23处取一条直线。那么,在一样的低FPR=0.23的状况下,红色分类器获得更高的PTR。也就代表,ROC越往上,分类器效果越好。咱们用一个标量值AUC来量化它。
auc其实就是ROC曲线围成的面积!!
在两个分类器的ROC曲线交叉的状况下,没法判断哪一个分类器性能更好,这时能够计算ROC曲线下面积AUC,做为性能度量,面积越大则越好。
为何使用Roc和Auc评价分类器
既然已经这么多标准,为何还要使用ROC和AUC呢?由于ROC曲线有个很好的特性:当测试集中的正负样本的分布变换的时候,ROC曲线可以保持不变。在实际的数据集中常常会出现样本类不平衡,即正负样本比例差距较大,并且测试数据中的正负样本也可能随着时间变化。
在上图中,(a)和(c)为Roc曲线,(b)和(d)为P-R曲线。
(a)和(b)展现的是分类其在原始测试集(正负样本分布平衡)的结果,(c)(d)是将测试集中负样本的数量增长到原来的10倍后,分类器的结果,能够明显的看出,ROC曲线基本保持原貌,而Precision-Recall曲线变化较大。
以上的Python代码实现你们能够参考这位的博客:https://www.jianshu.com/p/28ef55b779ca
相关系数是R哈~~~就是决定系数的开方!
正如题所说决定系数是来衡量回归的好坏,换句话说就是回归拟合的曲线它的拟合优度!也就是得分啦~~
决定系数它是表征回归方程在多大程度上解释了因变量的变化,或者说方程对观测值的拟合程度如何。
计算公式为:
决定系数越大表拟合优度越好!
Python中可直接调用score()方法来计算决定系数值。
score(self, x_test, y_test, sample_weight=None)
版权声明:本文为转载文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处连接和本声明。