最近在做多便签图像分类的任务,模型训练完之后,就需要使用测试集来验证模型的性能,一些比较通用的评价指标就是必不可少的工具,但是网上大多都是关于二分类以及多分类的评价指标,多便签分类的评价指标的介绍,还是比较少的,因此特开一贴,整理出四个常用的评价指标,并使用sklearn进行实现,如有谬误,还请各位指正!
ROC就是一条以假阳率为横轴,真阳率为纵轴的曲线,然后我们通过计算这条曲线下的面积,也就是AUC(Are under curve)作为评价指标,具体介绍可以看下这篇博客AUC,ROC我看到的最透彻的讲解。因此这个评价指标基本多用来衡量二分类,对于多便签的话,我们可以先计算每个标签的AUC,然后取平均作为结果。
具体实现如下:这里y_true需要是硬标签(0,1形式),y_pre需要软标签(0-1之间的小数即可)
from sklearn.metrics import roc_auc_score
def auROC(y_true,y_pred):
temp = []
for i in range(y_true.shape[1]):
try:
ROC = roc_auc_score(y_true[:, i], y_pred[:, i], average='macro', sample_weight=None)
except ValueError:
ROC = 0
#print("%d th AUROC: %f" % (i, ROC))
temp.append(ROC)
return np.mean(temp)
Map和ROC很像,也是计算曲线下的面积,区别就是Map的横坐标为recall,纵坐标为precision。具体介绍可以看这篇内容多标签图像分类任务的评价方法-mAP。同样的,我们需要先计算每个标签的AP值,然后取平均,就得到了Map。
具体实现如下:这里y_true需要是硬标签(0,1形式),y_pre需要软标签(0-1之间的小数即可)
from sklearn.metrics import average_precision_score
def compute_mAP(y_true, y_pred):
AP = []
for i in range(y_true.shape[1]):
AP.append(average_precision_score(y_true[:, i], y_pred[:, i]))
return np.mean(AP)
这个就相对会比较容易理解就是衡量单个样本所有标签的预测值和真实标签之间的差异程度,之前AUC和Map指标都是取单个标签的所有样本的预测值来进行计算的。相对的,HammingLoss则是取一个样本的所有预测值进行计算。具体可以参考多标签分类的评价指标
具体实现如下:这里y_true需要是硬标签(0,1形式),y_pre也需要硬标签,因此我们需要将y_pre的输出做个调整,一般就是手动设个阈值(一般取0.5),然后大于该阈值的,预测结果取1,小于的取0
from sklearn.metrics import hamming_loss
def computer_hamming_loss(y_true,y_pred):
y_hot = np.array(y_pred> 0.5, dtype=float)
HammingLoss = []
for i in range(self.label.shape[0]):
H = hamming_loss(y_true[i, :], y_hot[i, :])
HammingLoss.append(H)
return np.mean(HammingLoss)
OneErrorLoss其实就是先对单个样本的多有预测值进行排序,然后看下最大的那个预测值对应的真实标签是否为1,为1就记为0,否则就记为1,值越小也就越好。具体实现代码如下,这里吗没有使用Sklearn的工具,因为Sklearn内置的函数,需要将y_pre设置成硬标签,总感觉不太对,因为实际模型的输出都是软标签啊,对硬标签进行排序,会感觉怪怪的,因此自己写了一个,欢迎各位大佬能帮助答疑解惑。自己实现的代码如下:就是转换成列表,然后取y_pred中最大值对应的下标,然后判断真实值的标签是否为1。
def Computer_OneLoss(y_true, y_pred):
OneLoss = []
for i in range(y_true.shape[0]):
y_true_list = y_true[i, :].tolist()
y_pred_list = y_pred[i, :].tolist()
index = y_pred_list.index(max(y_pred_list))
if y_true_list[index]==1:
OneLoss.append(0)
elif y_true_list[index]==0:
OneLoss.append(1)
return np.mean(OneLoss)