引言 语义分割是像素级别的分类,其常用评价指标: Q: 什么是混淆矩阵? 下面是一句话解释混淆矩阵: 初步理解混淆矩阵,当以二分类混淆矩阵作为入门,多分类混淆矩阵都是以二分类为基础作为延伸的! Q: 什么是二分类? 对于二分类问题,将类别1称为正例(Positive),类别2称为反例(Negative),分类器预测正确记作真(True),预测错误记作(False),由这4个基本术语相互组合,构成混淆矩阵的4个基础元素,为: TP(True Positive):真正例,模型预测为正例,实际是正例(模型预测为类别1,实际是类别1) FP(False Positive):假正例,模型预测为正例,实际是反例 (模型预测为类别1,实际是类别2) FN(False Negative):假反例,模型预测为反例,实际是正例 (模型预测为类别2,实际是类别1) TN(True Negative):真反例,模型预测为反例,实际是反例 (模型预测为类别2,实际是类别2) 混淆矩阵示意图(参考:西瓜书 p30): 看到此处,可能对混淆矩阵有了初步了解,但大脑里依旧是:“混淆矩阵很混淆”的状态… 假如:宠物店有10只动物,其中6只狗,4只猫(真实值),现有一个模型将这10只动物进行分类,分类结果为(预测结果为):5只狗,5只猫(预测值),对分类结果画出对应混淆矩阵进行分析(狗:正例,类别1,猫:反例,类别2):() 等等…见此表是不是依旧懵逼?(那就对了…) 分析混淆矩阵的3个要点:(参考链接) ②矩阵每一行数字求和的值,其含义:真实值中,真实情况下属于该行对应类别的数目! ③矩阵每一列数字求和的值,其含义:预测值中,预测为该列对应类别的数目! 现小小总结一下这3个小点: 口诀:对角全为对,横看是真实,竖看是预测 此外:对列求和的理解挺“别扭”的,分享一下我的理解技巧:看列时,首先想到是以模型预测为出发点(既然是预测,肯定有对有错),其次是模型对该列对应类别的预测总数是多少,最后才判断预测的对与错,即:“列是预测,先定总数不管对错,后判正误”。 上面分析了一大堆,最终还是不够精炼,于是大佬们定义了几个公式: 准确率(Accuracy),对应:语义分割的像素准确率 PA 精准率(Precision),对应:语义分割的类别像素准确率 CPA 召回率(Recall),不对应语义分割常用指标 上述公式对应上述例子: 准确率:Accuracy = ( 5 +4 ) / (5 +4 + 0 + 1) = 0.9 精准率: 类别1(狗):P1 = 5 / (5 + 0) = 1 类别2(猫):P2 = 4 / (4 + 1) = 0.8 召回率: 类别1(狗):R1 = 5 / (5 + 1) = 0.83 类别2(猫):R2 = 4 / (4 + 0) = 1 上面是由二分类引出的关于混淆矩阵及其相关公式的介绍,语义分割一般都是多分类的,但也有二分类,对于二分类的语义分割评价指标可参考上述介绍理解,对于多分类的语义分割评价指标,其是基于二分类的思想进行发展延展的,即:将混淆矩阵行、列扩宽(类别增多),进行计算。 列举一个多分类(三类别)泛化一下知识点,防止读者学习过拟合! 以类别1为例,计算公式为: 准确率:Accuracy = (a + e + i) / (a + b + c + d + e +f + g + h + i) 精准率:P1 = a / (a + d + g) 召回率:R1 = a / (a + b + c) 更多计算例子,见: 先回顾一下上述的例子: 此例子中: 语义分割中: 进行上述区分,目的是让大家知道:不管进行分类的是动物,还是图片像素点,其混淆矩阵的获取、评价指标公式的计算都是一样的! 下面开始正题: 一般论文中,对语义分割模型的评估指标有: PA:像素准确率对应:准确率(Accuracy) 含义:预测类别正确的像素数占总像素数的比例 混淆矩阵计算: 对角线元素之和 / 矩阵所有元素之和 PA = (TP + TN) / (TP + TN + FP + FN) CPA:类别像素准确率对应:精准率(Precision) 含义:在类别 i 的预测值中,真实属于 i 类的像素准确率,换言之:模型对类别 i 的预测值有很多,其中有对有错,预测对的值占预测总值的比例 混淆矩阵计算: 类1:P1 = TP / (TP + FP) 类2:P2 = TN / (TN + FN) 类3:… MPA:类别平均像素准确率含义:分别计算每个类被正确分类像素数的比例,即:CPA,然后累加求平均 混淆矩阵计算: 每个类别像素准确率为:Pi(计算:对角线值 / 对应列的像素总数) MPA = sum(Pi) / 类别数 IoU:交并比含义:模型对某一类别预测结果和真实值的交集与并集的比值 混淆矩阵计算: 以求二分类:正例(类别1)的IoU为例 交集:TP,并集:TP、FP、FN求和 IoU = TP / (TP + FP + FN) MIoU:平均交并比含义:模型对每一类预测的结果和真实值的交集与并集的比值,求和再平均的结果 混淆矩阵计算: 以求二分类的MIoU为例 MIoU = (IoU正例p + IoU反例n) / 2 = [ TP / (TP + FP + FN) + TN / (TN + FN + FP) ] / 2 那么问题来了,交集和并集是如何来的? 继续以二分类为例说明,求正例(类别1)的IoU: 如图所示,A代表真实值(ground truth),B代表预测样本(prediction),预测值和真实值的关系如下: TP(True Positive): 橙色,TP = A ∩ B 预测正确,真正例,模型预测为正例,实际是正例(模型预测为类别1,实际是类别1) FP(False Positive): 黄色,FP = B - (A ∩ B) 预测错误,假正例,模型预测为正例,实际是反例 (模型预测为类别1,实际是类别2) FN(False Negative): 红色,FN = A - (A ∩ B) 预测错误,假反例,模型预测为反例,实际是正例 (模型预测为类别2,实际是类别1) TN(True Negative): 白色,TN = ~(A ∪ B) 预测正确,真反例,模型预测为反例,实际是反例 (模型预测为类别2,实际是类别2) 因此,可知正例(类别1)的IoU为: 此处有个比较疑惑的点是:TN有什么用? 如何找与P有关的混淆矩阵元素? 求正例的IoU,在真实情况和预测结果正例中各画一条线,线所过之处的元素则与正例有关! 同理,若求反例的IoU,则: 与求反例的IoU有关的元素有:TN FN FP,公式为: IoU = TN / (TN + FP + FN) 此时是不是有种豁然开朗的感觉? 对于IoU的理解,可延伸阅读一下: 上述对语义分割中常用5个评价指标进行了简介,下面列举一个例子,按照评价指标计算的三个步骤进行讲解: 步骤一:输入真实、预测图片当你跑完模型,得到网络预测结果图时,用标注图(ground truth)和预测图(pridiction)来得出网络的性能评估指标。语义分割评估指标代码大同小异,一般都是基于FCN源码的score.py中fast_hist()函数的思想来进行计算的。 左、右图进行对比可知,b中预测值有两个像素点分类错误,即: b 01,b 20 步骤二:求出混淆矩阵 混淆矩阵由:fast_hist(a, b, n)函数求出,此函数也是评估指标相关代码的关键! ''' FCN中score.py原版代码 参考链接:https://blog.csdn.net/qq_21368481/article/details/80424754 功能: 产生n×n的混淆矩阵 参数a:标注图(转换为一行输入),即真实的标签 参数b:预测图(转换为一行输入),即预测的标签 参数n: 类别数 ''' def fast_hist(a, b, n): #k为掩膜(去除了255这些点(即标签图中的白色的轮廓),其中的a>=0是为了防止bincount()函数出错) k = (a >= 0) & (a < n) #bincount()函数用于统计数组内每个非负整数的个数 #详见https://docs.scipy.org/doc/numpy/reference/generated/numpy.bincount.html return np.bincount(n * a[k].astype(int) + b[k], minlength=n**2).reshape(n, n) #核心代码 ''' fast_hist(a, b, n)函数的变形代码,都是为了求混淆矩阵 参考链接:https://blog.csdn.net/kkkkk0826/article/details/102962168 ''' def genConfusionMatrix(self, imgPredict, imgLabel): # remove classes from unlabeled pixels in gt image and predict mask = (imgLabel >= 0) & (imgLabel < self.numClass) label = self.numClass * imgLabel[mask] + imgPredict[mask] count = np.bincount(label, minlength=self.numClass**2) # 核心代码 confusionMatrix = count.reshape(self.numClass, self.numClass) return confusionMatrix上述函数的功能就是基于标注图和预测图求出混淆矩阵,进而求取相关评估指标的值! 下面对求混淆矩阵的核心代码,进行引用讲解(此大佬写得太好了,链接:FCN源码解读之score.py) 核心代码:np.bincount(n * a[k].astype(int) + b[k], minlength=n**2) 其作用是产生一行n * n个元素的向量,向量中的每个元素存储统计结果,假如该向量为d,则其中的d(i*n + j)表示预测结果为类别j,实际标签为类别i的所有像素点的数目。 将上述的a、b和n输入fast_hist(a, b, n),所产生的d为:d=(3,0,0,0,2,1,0,1,2),其中的d(1*3 + 1)=d(4)表示预测类别为1,实际标签也为1的所有像素点数目为2。 通过reshape(n, n)将向量d转换为3*3的矩阵,其结果如下表(该矩阵即为下表中的绿色部分): 其中绿色的3*3表格统计的含义,拿数字3所在的这一格为例,即预测标签中被预测为类别0的且其真实标签也为0的所有像素点数目之和。 下面继续引用大佬讲解,遵循:对角都对,横看真实,竖看预测 原则 ①绿色表格中对角线元素上的数字即为该类别预测正确的像素点数目,非对角线元素都是预测错误的,拿最后一行的数字1为例,其含义即为有一个原本应属于类别2的像素点被错误地预测为类别1; ②绿色表格的每一行求和得到的数字的含义是真实标签中属于某一类别的所有像素点数目,拿第一行为例,3+0+0=3,即真实属于类别0的像素点一共3个; ③绿色表格的每一列求和得到的数字的含义是预测为某一类别的所有像素点数目,拿第二列为例,0+2+1=3,即预测为类别1的所有像素点共有3个。 步骤三:评价指标计算根据混淆矩阵,则可进行评价指标计算了! PA = 对角线元素之和 / 矩阵所有元素之和 = (3 + 2 + 2) / (3 + 2 + 2 + 0 + 0 + 0 + 0 + 1 + 1)= 0.78 CPAPi = 对角线值 / 对应列的像素总数 MPA = sum(Pi) / 类别数 = ( P类别1 + P类别2 + P类别3 ) / 3 = 0.78 IoUIoUi = 对角线值 / 与该值有关元素的求和 [画线法] 第二种求法:(代码中用的求法:SAUB = SA + SB - SA∩B)(参考链接) MIoU = sum(IoUi) / 类别数 = (1 + 0.5 + 0.5) / 3 = 0.67 4 测试代码参考: 相关函数详解,请参考链接: 测评截图: 步骤二:获取混淆矩阵 (特别注意:此代码混淆矩阵,行为预测值,列为真实值,因此:CPA的计算需要翻转一下) 可计算上述值的和为:262144,即:图片512 * 512的值,表示模型共预测了512 * 512个像素点的类别 还可参考: 不知道我说清楚了吗? 4.4.2分类模型评判指标(一) - 混淆矩阵(Confusion Matrix) FCN源码解读之score.py 语义分割的评价指标——IoU (责任编辑:) |