混淆矩阵和语义分割评价指标

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

    语义分割评价指标

    混淆矩阵和评价指标

    https://cocodataset.org/#stuff-eval


    混淆矩阵Confusion Matrix)

    指标公式
    准确率、正确率 T P + T N ТР + T N + F P + F N \frac{TP + TN}{ ТР+ TN+FP+FN} ТР+TN+FP+FNTP+TN
    精确率、精度 P = T P ТР + F P P= \frac{TP }{ ТР+ FP} P=ТР+FPTP
    真正类率、召回率 R = T P ТР + F N R= \frac{TP }{ ТР+ FN} R=ТР+FNTP
    F1-Score精确度和召回率的调和平均值 F 1 = 2 P × R P + R F1=2\frac{P×R}{P+R} F1=2P+RP×R

    举例

    注大多数博客的类别像素准确率都是 T P T P + F P \frac{TP}{TP + FP} TP+FPTP而代码中都是 T P ТР + F N \frac{TP }{ ТР+ FN} ТР+FNTP其实类别像素准确率应该为混淆矩阵的召回率。

    指标公式举例
    像素准确率 P A = T P + T N ТР + T N + F P + F N PA = \frac{TP + TN}{ ТР+ TN+FP+FN} PA=ТР+TN+FP+FNTP+TN P A = a + e + i a + b + c + d + e + f + g + h + i PA = \frac{a+e+i}{ a+b+c+d+e+f+g+h+i} PA=a+b+c+d+e+f+g+h+ia+e+i
    类别像素准确率 C P A i = T P i T P i + F N i CPA_i =\frac{TP_i}{TP_i + FN_i } CPAi=TPi+FNiTPi C P A 类别 1 = a a + b + c ; C P A 类别 2 = e d + e + f ; C P A 类别 3 = i g + h + i CPA_{类别1} = \frac{a}{ a+b+c};CPA_{类别2} = \frac{e}{d+e+f};CPA_{类别3} = \frac{i}{ g+h+i} CPA类别1=a+b+ca;CPA类别2=d+e+fe;CPA类别3=g+h+ii
    类别平均像素准确率 M P A = Σ ( C P A i ) N MPA =\frac{Σ(CPA_i)}{N} MPA=NΣ(CPAi) M P A = C P A 类别 1 + C P A 类别 2 + C P A 类别 3 3 MPA= \frac{CPA_{类别1}+CPA_{类别2}+CPA_{类别3}}{3} MPA=3CPA类别1+CPA类别2+CPA类别3
    交并比 I o U i = T P i T P i + F P i + F N i IoU_i = \frac{TP_i}{TP_i + FP_i + FN_i} IoUi=TPi+FPi+FNiTPi I o U 类别 1 = a a + b + c + d + g IoU_{类别1} = \frac{a}{ a+b+c+d+g} IoU类别1=a+b+c+d+ga I o U 类别 2 = e d + e + f + b + h IoU_{类别2} = \frac{e}{ d+e+f+b+h} IoU类别2=d+e+f+b+he I o U 类别 3 = i g + h + i + c + f IoU_{类别3} = \frac{i}{ g+h+i+c+f} IoU类别3=g+h+i+c+fi
    平均交并比 M I o U = Σ ( I o U i ) N MIoU = \frac{Σ(IoU_i)}{N} MIoU=NΣ(IoUi) M I o U = I o U 类别 1 + I o U 类别 2 + I o U 类别 3 3 MIoU = \frac{IoU_{类别1} +IoU_{类别2} +IoU_{类别3} }{3} MIoU=3IoU类别1+IoU类别2+IoU类别3
    频权平均交并比 F W M I o U = ∑ k = 1 K n k T P k ∑ k = 1 K n k ∗ ( T P k + F P k + F N k ) FWMIoU =\frac{∑_{k=1}^Kn_kTP_k}{∑_{k=1}^Kn_k*(TP_k + FP_k + FN_k)} FWMIoU=k=1Knk(TPk+FPk+FNk)k=1KnkTPk f r e q 1 = a + b + c a + b + c + d + e + f + g + h + i freq1=\frac{a+b+c}{a+b+c+d+e+f+g+h+i} freq1=a+b+c+d+e+f+g+h+ia+b+c f r e q 2 = d + e + f a + b + c + d + e + f + g + h + i freq2=\frac{d+e+f}{a+b+c+d+e+f+g+h+i} freq2=a+b+c+d+e+f+g+h+id+e+f f r e q 3 = g + h + i a + b + c + d + e + f + g + h + i freq3=\frac{g+h+i}{a+b+c+d+e+f+g+h+i} freq3=a+b+c+d+e+f+g+h+ig+h+i F W M I o U = I o U 类别 1 ∗ f r e q 1 + I o U 类别 2 ∗ f r e q 2 + I o U 类别 3 ∗ f r e q 3 f r e q 1 + f r e q 2 + f r e q 3 FWMIoU =\frac{IoU_{类别1}* freq1 +IoU_{类别2} * freq2+IoU_{类别3}* freq3}{freq1 + freq2 + freq3} FWMIoU=freq1+freq2+freq3IoU类别1freq1+IoU类别2freq2+IoU类别3freq3
    F 1 − s c o r e F1-score F1score 2 ∗ T P / ( 2 ∗ T P + F P + F N ) 2*TP / (2*TP+FP+FN) 2TP/(2TP+FP+FN) F 1 类别 1 = 2 a 2 a + b + c + d + g + h F1_{类别1}=\frac{2a}{2a+b+c+d+g+h} F1类别1=2a+b+c+d+g+h2a F 1 类别 2 = 2 e 2 e + d + f + b + e + h F1_{类别2}=\frac{2e}{2e+d+f+b+e+h} F1类别2=2e+d+f+b+e+h2e F 1 类别 3 = 2 i 2 i + g + h + c + f F1_{类别3}=\frac{2i }{2i+g+h+c+f} F1类别3=2i+g+h+c+f2i F 1 = F 1 类别 1 + F 1 类别 2 + F 1 类别 3 3 F1=\frac{F1_{类别1}+F1_{类别2}+F1_{类别3}}{3} F1=3F1类别1+F1类别2+F1类别3
    Dice系数
    ROC和AUC
    RR/MRR
    """
    refer to https://github.com/jfzhang95/pytorch-deeplab-xception/blob/master/utils/metrics.py
    """
    import numpy as np
    
    __all__ = ['SegmentationMetric']
    
    """
                      预测
                    P    N
            P      TP    FN
    真实
            N      FP    TN
    """
    
    
    class SegmentationMetric(object):
        def __init__(self, numClass):
            self.numClass = numClass
            self.confusionMatrix = np.zeros((self.numClass,) * 2)
    
        def genConfusionMatrix(self, imgPredict, imgLabel):  # 同FCN中score.py的fast_hist()函数
            # 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
    
        def addBatch(self, imgPredict, imgLabel):
            assert imgPredict.shape == imgLabel.shape
            self.confusionMatrix += self.genConfusionMatrix(imgPredict, imgLabel)
    
        def pixelAccuracy(self):
            # 返回所有类别的整体像素准确度
            #  PA = acc = (TP + TN) / (TP + TN + FP + TN)
            acc = np.diag(self.confusionMatrix).sum() / self.confusionMatrix.sum()
            return acc
    
        def classPixelAccuracy(self):
            # 返回每个类别的像素精度称为精度的更准确方法
            # acc = (TP) / TP + FN
            classAcc = np.diag(self.confusionMatrix) / self.confusionMatrix.sum(axis=1)
            return classAcc  # 返回的是一个列表值如[0.90, 0.80, 0.96]表示类别1 2 3各类别的预测准确率
    
        def meanPixelAccuracy(self):
            classAcc = self.classPixelAccuracy()
            meanAcc = np.nanmean(classAcc)  # np.nanmean 求平均值nan表示遇到Nan类型其值取为0
            return meanAcc  # 返回单个值如np.nanmean([0.90, 0.80, 0.96, nan, nan]) = (0.90 + 0.80 + 0.96 / 3 =  0.89
    
        def IntersectionOverUnion(self):
            # Intersection = TP Union = TP + FP + FN
            # IoU = TP / (TP + FP + FN)
            intersection = np.diag(self.confusionMatrix)  # 取对角元素的值返回列表
            union = np.sum(self.confusionMatrix, axis=1) + np.sum(self.confusionMatrix, axis=0) - np.diag(
                self.confusionMatrix)  # axis = 1表示混淆矩阵行的值返回列表 axis = 0表示取混淆矩阵列的值返回列表
            IoU = intersection / union  # 返回列表其值为各个类别的IoU
            return IoU
    
        def meanIntersectionOverUnion(self):
            IoU = self.IntersectionOverUnion()
            mIoU = np.nanmean(IoU)  # 求各类别IoU的平均
            return mIoU
    
        def FrequencyWeightedIntersectionOverUnion(self):
            # FWIOU =     [(TP+FN)/(TP+FP+TN+FN)] *[TP / (TP + FP + FN)]
            freq = np.sum(self.confusionMatrix, axis=1) / np.sum(self.confusionMatrix)
            iu = np.diag(self.confusionMatrix) / (
                    np.sum(self.confusionMatrix, axis=1) + np.sum(self.confusionMatrix, axis=0) -
                    np.diag(self.confusionMatrix))
            FWIoU = (freq[freq > 0] * iu[freq > 0]).sum()
            return FWIoU
    
        def reset(self):
            self.confusionMatrix = np.zeros((self.numClass, self.numClass))
    
    
    if __name__ == '__main__':
        imgPredict = np.array([0, 1, 2, 2, 0, 1])
        imgLabel = np.array([0, 1, 2, 2, 1, 2])
        metric = SegmentationMetric(3)  # 3表示有3个分类
        metric.addBatch(imgPredict, imgLabel)
        pa = metric.pixelAccuracy()
        cpa = metric.classPixelAccuracy()
        mpa = metric.meanPixelAccuracy()
        IoU = metric.IntersectionOverUnion()
        mIoU = metric.meanIntersectionOverUnion()
        fwmIoU = metric.FrequencyWeightedIntersectionOverUnion()
        print('混淆矩阵:\n', metric.confusionMatrix)
        print('pa:\t', pa)
        print('cpa:\t', cpa)
        print('mpa:\t', mpa)
        print('IoU:\t', IoU)
        print('mIoU:\t', mIoU)
        print('FWmIoU:\t', fwmIoU)
    
    

    结果

    混淆矩阵:
     [[1. 0. 0.]
     [1. 1. 0.]
     [0. 1. 2.]]
    pa:	 0.6666666666666666
    cpa:	 [1.         0.5        0.66666667]
    mpa:	 0.7222222222222222
    IoU:	 [0.5        0.33333333 0.66666667]
    mIoU:	 0.5
    FWmIoU:	 0.5277777777777777
    
  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6