如何用tensorflow计算多标签前k个精度?

时间:2017-06-07 05:22:25

标签: python tensorflow multilabel-classification

我的任务是预测句子中五个最可能的标签。现在我从输出(密集连接)层获得了未缩放的日志:

with tf.name_scope("output"):
    scores = tf.nn.xw_plus_b(self.h_drop, W,b, name="scores")
    predictions = tf.nn.top_k(self.scores, 5) # should be the k highest score
with tf.name_scope("accuracy"):
    labels = input_y  # its shape is (batch_size, num_classes)
    # calculate the top k accuracy

现在预测就像[3,1,2,50,12](3,1 ......是得分最高的索引),而标签是"多热"形式:[0,1,0,1,1,0 ...]。  在python中,我可以简单地写

correct_preds = [input_y[i]==1 for i in predictions]
weighted = np.dot(correct_preds, [5,4,3,2,1]) # weighted by rank 
recall  = sum(correct_preds) /sum(input_y)
precision =sum(correct_preds)/len(correct_preds)

但是在tensorflow中,我用什么形式来完成这项任务?

2 个答案:

答案 0 :(得分:4)

解决方案

我编写了一个如何进行计算的例子。此示例中的所有输入都编码为 tf.constant ,但您当然可以替换变量。

主要技巧是矩阵乘法。首先将 input_y 重新整形为[1x5]一个名为 to_top5 的矩阵的2d倍。第二个是 weighted_matrix correct_preds

代码

import tensorflow as tf

input_y = tf.constant( [5,2,9,1] , dtype=tf.int32 )

predictions = tf.constant( [[9,3,5,2,1],[8,9,0,6,5],[1,9,3,4,5],[1,2,3,4,5]])

to_top5       = tf.constant( [[1,1,1,1,1]] , dtype=tf.int32 )
input_y_for_top5 = tf.matmul( tf.reshape(input_y,[-1,1]) , to_top5 )

correct_preds = tf.cast( tf.equal( input_y_for_top5 , predictions ) , dtype=tf.float16 )

weighted_matrix = tf.constant( [[5.],[4.],[3.],[2.],[1.]] , dtype=tf.float16 )

weighted = tf.matmul(correct_preds,weighted_matrix)

recall = tf.reduce_sum(correct_preds) / tf.cast( tf.reduce_sum(input_y) , tf.float16)
precision = tf.reduce_sum(correct_preds) / tf.constant(5.0,dtype=tf.float16)

## training
# Run tensorflow and print the result
with tf.Session() as sess:
  print "\n\n=============\n\n"
  print "\ninput_y_for_top5"
  print sess.run(input_y_for_top5)
  print "\ncorrect_preds"
  print sess.run(correct_preds)
  print "\nweighted"
  print sess.run(weighted)
  print "\nrecall"
  print sess.run(recall)
  print "\nprecision"
  print sess.run(precision)
  print "\n\n=============\n\n"

输出

=============

input_y_for_top5
[[5 5 5 5 5]
 [2 2 2 2 2]
 [9 9 9 9 9]
 [1 1 1 1 1]]

correct_preds
[[ 0.  0.  1.  0.  0.]
 [ 0.  0.  0.  0.  0.]
 [ 0.  1.  0.  0.  0.]
 [ 1.  0.  0.  0.  0.]]

weighted
[[ 3.]
 [ 0.]
 [ 4.]
 [ 5.]]

recall
0.17651

precision
0.6001

=============

摘要

以上示例显示批次大小为4。

第一批 y_label 5 ,这意味着索引为5的元素是第一批的正确标签。此外,第一批的预测是[9,3,5,2,1],这意味着预测函数认为第9个元素最有可能,那么元素3是下一个最有可能的,依此类推。

假设我们想要一个批量大小为3的示例,然后使用以下代码

input_y = tf.constant( [5,2,9] , dtype=tf.int32 )
predictions = tf.constant( [[9,3,5,2,1],[8,9,0,6,5],[1,9,3,4,5]])

如果我们用上面的代码替换程序,我们可以看到它确实正确地计算了批量大小为3的所有内容。

答案 1 :(得分:1)

受上面@wontonimo回答的启发,我使用矩阵运算和tf.reshape,tf.gather实现了一个方法。标签张量是“多热的”,例如[[0,1,0,1],[1,0,0,1]。预测张量由tf.nn.top_k获得,看起来像[[3,1],[0,1]]。这是代码:

top_k_pred = tf.nn.top_k(logits, 5)
tmp1 = tf.reshape(tf.range(batch_size)*num_classes, (-1,1))
idx_incre = top_k_pred[1] + tf.concat([tmp1]*5,1)
correct_preds = tf.gather(tf.reshape(y_label, (-1,), tf.reshape(idx_incre, (-1,)))
correct_preds = tf.reshape(correct_pred, (batch_size, 5))
weighted = correct_preds * [[5],[4],[3],[2],[1]]