如何使用 tensorflow 计算多标签前 k 个精度?
how can I calculate the multi-label top k precisions with tensorflow?
我的任务是预测句子中最有可能出现的五个标签。现在我从输出(密集连接)层得到了未缩放的逻辑:
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... 是最高分的索引),而标签是 "multi-hot" 形式:[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中,我应该用什么形式来完成这个任务呢?
解决方案
我编写了一个如何进行计算的示例。此示例中的所有输入都编码为 tf.constant 但当然您可以替换您的变量。
主要技巧是矩阵乘法。首先是 input_y 重塑为 [1x5] 个矩阵的 2d 倍,称为 to_top5。第二个是 correct_preds 由 weighted_matrix.
代码
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的元素是第一批的正确标签。此外,第一批的 prediction 是 [9,3,5,2,1] 这意味着 prediction 函数认为第 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 的所有内容。
受上面@wontonimo'回答的启发,我实现了一个使用矩阵操作和tf.reshape、tf.gather的方法。标签张量是 "multi-hot",例如[[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]]
我的任务是预测句子中最有可能出现的五个标签。现在我从输出(密集连接)层得到了未缩放的逻辑:
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... 是最高分的索引),而标签是 "multi-hot" 形式:[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中,我应该用什么形式来完成这个任务呢?
解决方案
我编写了一个如何进行计算的示例。此示例中的所有输入都编码为 tf.constant 但当然您可以替换您的变量。
主要技巧是矩阵乘法。首先是 input_y 重塑为 [1x5] 个矩阵的 2d 倍,称为 to_top5。第二个是 correct_preds 由 weighted_matrix.
代码
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的元素是第一批的正确标签。此外,第一批的 prediction 是 [9,3,5,2,1] 这意味着 prediction 函数认为第 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 的所有内容。
受上面@wontonimo'回答的启发,我实现了一个使用矩阵操作和tf.reshape、tf.gather的方法。标签张量是 "multi-hot",例如[[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]]