Tensorflow中多类分类的按类别精确度和召回率是什么?

18

当使用Tensorflow进行多类分类时,有没有一种方法可以获得每个类的精确度或召回率。

例如,如果我有来自每批次的y_true和y_pred,是否有一种功能性的方式可以在有多于2个类的情况下获取每个类的精确度或召回率。

7个回答

7
这是一个与n=6类有关的问题的解决方案,对于更多类别的情况,这个解决方案可能会变得很慢,建议使用映射而不是循环。
假设您在张量的行中具有独热编码的类标签 "labels" 和张量 "logits"(或后验概率),然后如果 "n" 是类的数量,请尝试以下方法:
y_true = tf.argmax(labels, 1)
y_pred = tf.argmax(logits, 1)

recall = [0] * n
update_op_rec = [[]] * n

for k in range(n):
    recall[k], update_op_rec[k] = tf.metrics.recall(
        labels=tf.equal(y_true, k),
        predictions=tf.equal(y_pred, k)
    )

请注意,在tf.metrics.recall中,变量labelspredictions被设置为布尔向量,就像在2个变量的情况下一样,这允许使用该函数。


3

我已经被这个问题困扰了相当长的时间。我知道可以使用sklearn来解决这个问题,但我真的想通过Tensorflow的API来解决它。通过阅读它的代码,我终于搞清楚了这个API是如何工作的。

tf.metrics.precision_at_k(labels, predictions, k, class_id)
  • Firstly, let's assume this is a 4 classes problem.
  • Secondly, we have two samples which their labels are 3 and 1 and their predictions are [0.5,0.3,0.1,0.1], [0.5,0.3,0.1,0.1] .According to our predictions, we can get the result that the two samples has been predicted as 1,1.
  • Thirdly, if you want to get the precision of class 1, use the formula TP/(TP+FP), and we assume the result is 1/(1+1)=0.5. Because the two samples both have been predicted as 1, but one of the them is actually 3, so the TP is 1, the FP is 1, and the result is 0.5.
  • Finally, let's use this API to verify our assumption.

    import tensorflow as tf
    
    labels = tf.constant([[2],[0]],tf.int64)
    predictions = tf.constant([[0.5,0.3,0.1,0.1],[0.5,0.3,0.1,0.1]])
    
    metric = tf.metrics.precision_at_k(labels, predictions, 1, class_id=0)
    
    sess = tf.Session()
    sess.run(tf.local_variables_initializer())
    
    precision, update = sess.run(metric)
    print(precision) # 0.5
    

注意

  • k 不是类别数量。它表示我们想要排序的项目数量,因此预测结果的最后一维必须与k的值相同。

  • class_id 表示我们想要二元指标的类别。

  • 如果 k=1,则意味着我们不会对预测进行排序,因为我们实际上要做的是二元分类,但是涉及到不同的类别。因此,如果我们对预测进行排序,class_id 将会混淆,结果将会错误。

  • 还有一件重要的事情是,如果我们想要得到正确的结果,标签的输入应该减去1,因为 class_id 实际上表示 标签的索引,而标签的下标从0开始


3

我认为使用tf.metrics.precision/recall函数无法进行多类别的精确度、召回率和f1值计算。对于三类情况,您可以像这样使用sklearn:

from sklearn.metrics import precision_recall_fscore_support as score

prediction = [1,2,3,2] 
y_original = [1,2,3,3]

precision, recall, f1, _ = score(y_original, prediction)

print('precision: {}'.format(precision))
print('recall: {}'.format(recall))
print('fscore: {}'.format(f1))

这将打印一个精度和召回率的数组值,但您可以根据喜好格式化它。

2
在TensorFlow中有一种方法可以实现这个。
tf.metrics.precision_at_k(labels, predictions, k, class_id)

将k设置为1并设置对应的class_id。例如,设置class_id=0以计算第一类的精度。


1

1
这些函数不会为每个类别单独计算指标,正如问题所要求的那样。如果某些类别在数据中出现的频率比其他类别更高,则这些指标将被这些频繁出现的类别所主导。通常希望为每个类别计算单独的召回率和精确度,然后对它们进行平均以获得整体值(类似于 tf.metrics.mean_per_class_accuracy)。使用不平衡数据时,这些值可能与使用 tf.metrics.recalltf.metrics.precision 获得的值不同。 - Avi
1
实际上,我弄错了;tf.metrics.mean_per_class_accuracy 做的是不同的事情,并不是这个问题的好参考。 - Avi

0

这里有一个完整的例子,从使用Tensorflow进行预测到通过scikit-learn进行报告:

import tensorflow as tf
from sklearn.metrics import classification_report

# given trained model `model` and test vector `X_test` gives `y_test`
# where `y_test` and `y_predicted` are integers, who labels are indexed in 
# `labels`
y_predicted = tf.argmax(model.predict(X_test), axis=1)

# Confusion matrix
cf = tf.math.confusion_matrix(y_test, y_predicted)
plt.matshow(cf, cmap='magma')
plt.colorbar()
plt.xticks(np.arange(len(labels)), labels=labels, rotation=90)
plt.yticks(np.arange(len(labels)), labels=labels)
plt.clim(0, None)

# Report
print(classification_report(y_test, y_predicted, target_names=labels))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接