tf.nn.softmax_cross_entropy_with_logits,sparse_softmax_....

一、tf.nn.softmax_cross_entropy_with_logits

在深度学习的编程题,里面我们碰到了关于tf.nn.sigmoid_cross_entropy_with_logits,下面我们将翻译官网给其提供的介绍,并举例说明!

函数原型:tf.nn.softmax_cross_entropy_with_logits(_sentinel=None,labels=None,logits=None,dim=-1,name=None)

这个函数之后在未来的版本中会被移除,哎呀先不管了,学着吧!之后会更新为:tf.nn.softmax_cross_entropy_with_logits_v2()好像就可满足再反向传播的时候允许梯度流进标签的输入中。

在这里需要强调一点,之前介绍的tf.nn.sigmoid_cross_entropy_with_logits这个允许我们所属于类可以有多个,本文介绍的函数呢,每一个样本只对应一个类别。就像一个猪的图片,他只能被预测为猪,不能是猪和狗都是。

注意:尽管我们的类别需要是相互排斥的,但是概率却不需要。labels的每一行是一个概率分布,如果不是的话,梯度的计算就不对了。

警告:这个操作希望的是没有softmax之前的logits,它会在操作内部自动的给logits计算softmax,所以不要给你的logits进行softmax操作再传给我们的这个函数,会出错哒!

一般,我们的logits和labels的大小都是[batch_size,num_classes],每一行都是一个可以支持更高的维度,通过dim这个参数来指定类别的维度。

为了避免出错,这个参数的传递必须带上命名的参数。

dim:表示的是类别的维度,默认为-1表示的是最后一个维度。

函数返回的是一个向量,所以你还需要最后计算tf.reduce_mean()来得到最终的结果cost。

代码:下面的代码是单个样本的情况,你可以发现自己利用公式来求解,也就是你需要先将自己的网络的最后一层输出(softmax之前)的结果先求softmax(利用公式:假设你的神经网络的单样本的输出为Z^{[L]}=[z_{1},z_{2},...z_{c}]^{T},其中的c是代表的是总共的类别数,那么这个结果给softmax的输出假设为S=[e^{z_{1}},e^{z_{2}},....e^{z_{c}}]^{T}/\sum_{i=1}^{c}e^{z_{i}}),然后在计算loss=-\sum_{i}^{c}label_i*log(s_i).

下面的例子的解释:

import tensorflow as tf
#下面的代码面对的是单个样本的情况:
logits = tf.constant([5.,2.,-1.,3.])
labels = tf.constant([1.0,0.0, 0.0, 0.0])
#自己计算需要先计算softmax,然后在计算交叉熵
softmax = tf.nn.softmax(logits)
cross_entropy1 = -tf.reduce_sum(labels * tf.log(softmax))
#利用tf的函数计算无需讲网络的输出传给softmax再传给函数的logits
result=tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=labels)
cross_entropy2 = tf.reduce_sum(result)  # dont forget tf.reduce_sum()!!

with tf.Session() as sess:
    print("softmax =",sess.run(softmax))
    print("cross_entropy result=",sess.run(cross_entropy1))
    print("result =",sess.run(result))
    print("tf function's result=",sess.run(cross_entropy2))

结果:

softmax = [0.84203357 0.04192238 0.00208719 0.11395685]
cross_entropy result= 0.1719354
result = 0.17193538
tf function's result= 0.17193538

解释:还是上图简单,图像是歪的,就是调不过来。。。

代码:多个样本,输入的shape为[batch_size,num_classes]

import tensorflow as tf
#下面的代码面对的是多个样本的情况:
logits = tf.constant([[5.,2.,-1.,3.],[1.,2.,3.,4.]])
labels = tf.constant([[1.0,0.0, 0.0, 0.0],[0.0,0.0,0.0,1.0]])
#自己计算需要先计算softmax,然后在计算交叉熵
softmax = tf.nn.softmax(logits)
cross_entropy1 = -tf.reduce_sum(labels * tf.log(softmax))
#利用tf的函数计算无需讲网络的输出传给softmax再传给函数的logits
result=tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=labels)
cross_entropy2 = tf.reduce_sum(result)  # dont forget tf.reduce_sum()!!

with tf.Session() as sess:
    print("softmax =",sess.run(softmax))
    print("cross_entropy result=",sess.run(cross_entropy1))
    print("result =",sess.run(result))
    print("tf function's result=",sess.run(cross_entropy2))

结果:

softmax = [[0.84203357 0.04192238 0.00208719 0.11395685]
 [0.0320586  0.08714432 0.23688284 0.6439143 ]]
cross_entropy result= 0.61212504
result = [0.17193538 0.4401897 ]
tf function's result= 0.61212504

解释:就是之前的loss求解的时候是多个样本了,所以还要对样本求和

二、tf.nn.sparse_softmax_cross_entropy_with_logits()

这个跟上面的那个唯一的区别就是不需要你传入的labels是one-hot类型,可以是直接的数字,将labels转成one-hot的步骤内置在这个里面了函数里面了修改之前的代码可以看出差别:

注意这里的logits类型必须是float16, float32, or float64。这里的labels的类型必须是int32 or int64.

代码:很显然结果跟之前是一致的,但是这里的labels跟之前的不一样。

import tensorflow as tf

logits = tf.constant([[5.,2.,-1.,3.],[1.,2.,3.,4.]])
labels = tf.constant([0,3])

result=tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=labels)
cross_entropy = tf.reduce_sum(result)  # dont forget tf.reduce_sum()!!

with tf.Session() as sess:
    print("result =",sess.run(result))
    print("tf function's result=",sess.run(cross_entropy))

结果:

result = [0.17193538 0.4401897 ]
tf function's result= 0.61212504

猜你喜欢

转载自blog.csdn.net/m0_37393514/article/details/81407272