tf.metrics.sparse_average_precision_at_k 和 tf.metrics.precision_at_k的自己理解

tensorflow最大的问题就是大家都讲算法,不讲解用法,API文档又全是英文的,看起来好吃力,理解又不到位。当然给数学博士看的话,就没问题的。

最近看了一系列非常不错的文章,做一下记录:

https://www.zhihu.com/people/hong-lan-99/activities

https://github.com/lanhongvp

https://blog.csdn.net/qq_37747262

https://blog.csdn.net/qq_37747262/article/details/82223155

特别是关于他的填坑记系列的。我发现我看不懂 tf.metrics.precision_at_k这个代码,在知乎上也找到了他解释的文档。奈何解释的我看不太懂。

以下是他在知乎上插入的代码

作者:洪澜
链接:https://www.zhihu.com/question/277184041/answer/480219663
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

import tensorflow as tf
import numpy as np

y_true = np.array([[2], [1], [0], [3], [0], [1]]).astype(np.int64)
y_true = tf.identity(y_true)

y_pred = np.array([[0.1, 0.2, 0.6, 0.1],
                   [0.8, 0.05, 0.1, 0.05],
                   [0.3, 0.4, 0.1, 0.2],
                   [0.6, 0.25, 0.1, 0.05],
                   [0.1, 0.2, 0.6, 0.1],
                   [0.9, 0.0, 0.03, 0.07]]).astype(np.float32)
y_pred = tf.identity(y_pred)

_, m_ap = tf.metrics.sparse_average_precision_at_k(y_true, y_pred, 2)

sess = tf.Session()
sess.run(tf.local_variables_initializer())

stream_vars = [i for i in tf.local_variables()]
print((sess.run(stream_vars)))

tf_map = sess.run(m_ap)
print(tf_map)

tmp_rank = tf.nn.top_k(y_pred,4)
print(sess.run(tmp_rank))

以下是他的解释

作者:洪澜
链接:https://www.zhihu.com/question/277184041/answer/480219663
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 简单解释一下,首先y_true代表标签值(未经过one-hot)shape:(batch_size, num_labels) ,y_pred代表预测值(logit值) ,shape:(batch_size, num_classes)
  • 其次,要注意的是tf.metrics.sparse_average_precision_at_k中会采用top_k根据不同的k值对y_pred进行排序操作 ,所以tmp_rank是为了帮助大噶理解究竟y_pred在函数中进行了怎样的转换。
  • 然后,stream_vars = [i for i in tf.local_variables()]这一行是为了帮助大噶理解 tf.metrics.sparse_average_precision_at_k创建的tf.local_varibles 实际输出值,进而可以更好地理解这个函数的用法。
  • 具体看这个例子,当k=1时,只有第一个batch的预测输出是和标签匹配的 ,所以最终输出为:1/6 = 0.166666 ;当k=2时,除了第一个batch的预测输出,第三个batch的预测输出也是和标签匹配的,所以最终输出为:(1+(1/2))/6 = 0.25
======
但是还是不太理解他的解释:为什么K=1的时候回算出来匹配的是1,而k=2时算出来是0.25
经过自己调试和摸索,终于明白了作者的用意:
 
#调用以下代码
tmp_rank = tf.nn.top_k(y_pred,4)
print(sess.run(tmp_rank))
'''
就会得到类似的东西
TopKV2(values=array([[0.6 , 0.2 , 0.1 , 0.1 ],
       [0.8 , 0.1 , 0.05, 0.05],
       [0.4 , 0.3 , 0.2 , 0.1 ],
       [0.6 , 0.25, 0.1 , 0.05],
       [0.6 , 0.2 , 0.1 , 0.1 ],
       [0.9 , 0.07, 0.03, 0.  ]], dtype=float32), indices=array([[2, 1, 0, 3],
       [0, 2, 1, 3],
       [1, 0, 3, 2],
       [0, 1, 2, 3],
       [2, 1, 0, 3],
       [0, 3, 2, 1]]))
'''

通过对tf.nn.top_k的调用以及返回的结果,可以明白函数大概有几个作用

1. 把y_pred中的数值进行了从大到小的重新排列

2. 计算得到现在位置上的数据原来所在的位置

K值的作用是指定只计算多少个。作者的解释

  • 具体看这个例子,当k=1时,只有第一个batch的预测输出是和标签匹配的 ,所以最终输出为:1/6 = 0.166666 ;当k=2时,除了第一个batch的预测输出,第三个batch的预测输出也是和标签匹配的,所以最终输出为:(1+(1/2))/6 = 0.25

就比较容易解释了。简单的理解,就是后面输出的原来的位置和y_true进行比较,如果匹配就增加一,以前是一列数据去比较,现在成了K列,然后得到的数字/K。那么这个函数这样做的目的和意义在哪里呢?

我个人的理解,如果K=1的时候,是预测概率最大的和标签匹配的概率是多少,K=2的时候,计算的是概率最大的列和其次的最大概率恰好与标签匹配的概率的平均准确度有多少。

 
原文地址:https://www.cnblogs.com/bbird/p/11468864.html