Tensorflow中的多类分类的类别精确度和召回率?

时间:2017-08-10 03:31:15

标签: python machine-learning tensorflow classification

使用张量流进行多类分类时,是否有办法获得每类精度或召回。

例如,如果我有每个批次的y_true和y_pred,如果我有超过2个类,是否有一种功能性的方法来获得每个类的精度或召回。

7 个答案:

答案 0 :(得分:5)

这是一个解决方案,适用于n = 6类的问题。如果你有更多的类,这个解决方案可能很慢,你应该使用某种映射而不是循环。

假设在张量labels中有一个热编码类标签,在张量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变量情况,允许使用该函数。

答案 1 :(得分:3)

我相信你不能用tf.metrics.precision/recall函数做多类精度,回忆,f1。你可以使用这样的sklearn来实现3类场景:

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 :(得分:3)

我很困惑这个问题很长时间了。我知道sklearn可以解决此问题,但我真的很想通过Tensorflow的API解决此问题。通过阅读其代码,我终于弄清楚了该API的工作原理。

tf.metrics.precision_at_k(labels, predictions, k, class_id)
  • 首先,我们假设这是一个 4类问题。
  • 第二,我们有两个样本,它们的标签分别为3和1 ,并且其预测为[0.5,0.3,0.1,0.1],[0.5,0.3,0.1,0.1] < / strong>。根据我们的预测,我们可以得出两个样本被预测为 1,1 的结果。
  • 第三,如果要获得 1级的精度,请使用公式 TP /(TP + FP),我们假设结果为 1 /(1 + 1)= 0.5 。由于两个样本均被预测为 1 ,但其中一个样本实际上为 3 ,因此 TP为1 FP为1 结果为0.5
  • 最后,让我们使用此API来验证我们的假设。

    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实际上表示标签的索引< / strong>,并且标签的下标以0 开头。

答案 3 :(得分:2)

有一种方法可以在TensorFlow中执行此操作。

tf.metrics.precision_at_k(labels, predictions, k, class_id)

设置k = 1并设置相应的class_id。例如,class_id = 0来计算第一类的精度。

答案 4 :(得分:2)

2个事实:

  1. 如其他答案所述,Tensorflow内置指标precisionrecall 不支持多类(文档中说{{1} })

  2. 通过指定will be cast to bool或使用class_id来使用precision_at_k,可以得到对所有分数并以正确的方式从labelspredictions

因为这不令人满意且不完整,所以我写了 tf_metrics ,这是一个用于多类指标的简单程序包,您可以在github上找到它。它支持tf.bool之类的多种平均方法。

示例

scikit-learn

答案 5 :(得分:1)

我相信TF还没有提供这样的功能。根据文档(https://www.tensorflow.org/api_docs/python/tf/metrics/precision),它表示标签和预测都将转换为bool,因此它仅与二进制分类相关。也许有可能对这些例子进行单热编码,它会起作用吗?但不确定这一点。

答案 6 :(得分: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))