JuneoXIE
4/25/2019 - 8:20 AM

混淆矩阵与ROC曲线

混淆矩阵

  • 准确率 Accuracy:
  • 精确率(查准率)Precision:
  • 召回率(查全率)Recall:

    基本函数:
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
# 使用confusion_matrix()得出最终的混淆矩阵
conf_mx = confusion_matrix(y_train, y_train_pred)
# 使用 Matplotlib 的 matshow() 函数,将混淆矩阵以图像的方式呈现
plt.matshow(conf_mx, cmap=plt.cm.gray)

更好的可视化效果:
将展示标签label,真实结果y_true,预测结果y_pred改成自己的数据即可

from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
import numpy as np

# labels表示你不同类别的代号,比如这里的demo中有13个类别
labels = ['A', 'B', 'C', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O']

# y_true代表真实的label值 y_pred代表预测得到的lavel值
y_true = np.loadtxt('../Data/re_label.txt')
y_pred = np.loadtxt('../Data/pr_label.txt')

tick_marks = np.array(range(len(labels))) + 0.5

def plot_confusion_matrix(cm, title='Confusion Matrix', cmap=plt.cm.binary):
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    xlocations = np.array(range(len(labels)))
    plt.xticks(xlocations, labels, rotation=90)
    plt.yticks(xlocations, labels)
    plt.ylabel('True label')
    plt.xlabel('Predicted label')


cm = confusion_matrix(y_true, y_pred)
np.set_printoptions(precision=2)
cm_normalized = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
print cm_normalized
plt.figure(figsize=(12, 8), dpi=120)

ind_array = np.arange(len(labels))
x, y = np.meshgrid(ind_array, ind_array)

for x_val, y_val in zip(x.flatten(), y.flatten()):
    c = cm_normalized[y_val][x_val]
    if c > 0.01:
        plt.text(x_val, y_val, "%0.2f" % (c,), color='red', fontsize=7, va='center', ha='center')
# offset the tick
plt.gca().set_xticks(tick_marks, minor=True)
plt.gca().set_yticks(tick_marks, minor=True)
plt.gca().xaxis.set_ticks_position('none')
plt.gca().yaxis.set_ticks_position('none')
plt.grid(True, which='minor', linestyle='-')
plt.gcf().subplots_adjust(bottom=0.15)

plot_confusion_matrix(cm_normalized, title='Normalized confusion matrix')
# show confusion matrix
plt.savefig('../Data/confusion_matrix.png', format='png')
plt.show()

人脸识别中常用指标TAR,FAR 和 FRR,ERR

做人脸识别时会给出两张图像让算法判断两张图片是不是同一个人。一般先将两张图片表示成两个高维的特征向量,然后计算两个特征向量的相似度或者距离。在这里定义TAR,FAR,FRR时公式中分数就是指的相似度。在比较的过程中我们希望同一个人的图像相似度比较高,不同人的相似度比较低。我们会给定一个相似度阈值T,比如0.6, 如果两张图像的相似度大于T我们就认为两张图片是一个人的,如果小于T我们就认为两证图像 是不同人的。

  • TAR(True Accept Rate):正确接受的比例,把相同的人正确识别成相同的人
  • FAR(False Accept Rate):错误接受的比例,把不同的人识别成相同的人
  • FRR(False Reject Rate):错误拒绝率,把相同的人的图像当做不同人
  • EER(Equal Error Rate): 等误率, 取某个T值时,使得FAR = FRR时,的FAR或FRR值。
  • TAR @ FAR=0.00100: 在FAR=0.00100的情况下的TAR值
    注:所谓的接受就是在进行人脸验证的过程中,两张图像被认为是同一个人。

ROC曲线

  • 真正例率(True Positive Rate,TPR)相当于人脸识别中的TAR
  • 假正例率(False Positive Rate。FPR)相当于人脸识别中的FAR
  • TPR-FPR 曲线:

    图中的红色曲线和蓝色曲线分别表示了两个不同的分类器的TPR-FPR曲线,曲线上的任意一点都对应了一个t(阈值)值。该曲线就是ROC曲线(receiver operating characteristic curve)。
  • ROC曲线的特征:
    • 一定经过(0,0)点,此时t=1,没有预测为P的值,TP和FP都为0
    • 一定经过(1,1)点,此时t=0,全都预测为P
    • 最完美的分类器(完全区分正负样例):(0,1)点,即没有FP,全是TP
    • 曲线越是“凸”向左上角,说明分类器效果越好
    • 随机预测会得到(0,0)和(1,1)的直线上的一个点
    • 曲线上离(0,1)越近的点分类效果越好,对应着越合理的t

从图中可以看出,红色曲线所代表的分类器效果好于蓝色曲线所表示的分类器。

  • 利用ROC的其他评估标准
    • AUC(area under thecurve),也就是ROC曲线的下夹面积,越大说明分类器越好,最大值是1,图中的蓝色条纹区域面积就是蓝色曲线对应的 AUC
    • EER(equal error rate),也就是FPR=FNR的值
      可以画一条从(0,1)到(1,0)的直线,此时的横坐标是FNR。找到交点,图中的A、B两点,此时FPR等于FNR,假正率等于假负率,即等误率(EER)。

绘制ROC曲线的代码:

# 引入必要的库
import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle
from sklearn import svm, datasets
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import label_binarize
from sklearn.multiclass import OneVsRestClassifier
from scipy import interp

# 加载数据
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 将标签二值化
y = label_binarize(y, classes=[0, 1, 2])
# 设置种类
n_classes = y.shape[1]

# 训练模型并预测
random_state = np.random.RandomState(0)
n_samples, n_features = X.shape

# shuffle and split training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.5,random_state=0)

# Learn to predict each class against the other
classifier = OneVsRestClassifier(svm.SVC(kernel='linear', probability=True,
                                 random_state=random_state))
y_score = classifier.fit(X_train, y_train).decision_function(X_test)

# 计算每一类的ROC
fpr = dict()
tpr = dict()
roc_auc = dict()
for i in range(n_classes):
    fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_score[:, i])
    roc_auc[i] = auc(fpr[i], tpr[i])

# Compute micro-average ROC curve and ROC area(方法二)
fpr["micro"], tpr["micro"], _ = roc_curve(y_test.ravel(), y_score.ravel())
roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])

# Compute macro-average ROC curve and ROC area(方法一)
# First aggregate all false positive rates
all_fpr = np.unique(np.concatenate([fpr[i] for i in range(n_classes)]))
# Then interpolate all ROC curves at this points
mean_tpr = np.zeros_like(all_fpr)
for i in range(n_classes):
    mean_tpr += interp(all_fpr, fpr[i], tpr[i])
# Finally average it and compute AUC
mean_tpr /= n_classes
fpr["macro"] = all_fpr
tpr["macro"] = mean_tpr
roc_auc["macro"] = auc(fpr["macro"], tpr["macro"])

# Plot all ROC curves
lw=2
plt.figure()
plt.plot(fpr["micro"], tpr["micro"],
         label='micro-average ROC curve (area = {0:0.2f})'
               ''.format(roc_auc["micro"]),
         color='deeppink', linestyle=':', linewidth=4)

plt.plot(fpr["macro"], tpr["macro"],
         label='macro-average ROC curve (area = {0:0.2f})'
               ''.format(roc_auc["macro"]),
         color='navy', linestyle=':', linewidth=4)

colors = cycle(['aqua', 'darkorange', 'cornflowerblue'])
for i, color in zip(range(n_classes), colors):
    plt.plot(fpr[i], tpr[i], color=color, lw=lw,
             label='ROC curve of class {0} (area = {1:0.2f})'
             ''.format(i, roc_auc[i]))

plt.plot([0, 1], [0, 1], 'k--', lw=lw)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Some extension of Receiver operating characteristic to multi-class')
plt.legend(loc="lower right")
plt.show()