欢迎关注微信公众号:python科技园
目录
1. 函数功能
2. 语法结构
3. 实现步骤
第一步:计算 Softmax
第二步:计算 Cross Entropy
4. 示例 sparse_softmax_cross_entropy_with_logits
5. 示例 softmax_cross_entropy_with_logits
6. 补充说明
函数讲解
1. 函数功能
多分类交叉熵计算函数。它适用于每个类别相互独立且排斥的情况,例如一幅图只能属于一类,而不能同时包含一条狗和一头大象。
2. 语法结构
tf.nn.sparse_softmax_cross_entropy_with_logits(labels=None, logits=None, name=None)
3. 实现步骤
函数如其名,具体分为两个步骤:Softmax 和 Cross Entropy。
第一步:计算 Softmax
在进行文本分类或图像识别等任务时,神经网络输出层的神经元个数通常就是我们要分类的类别数量。Softmax函数的作用就是将每个类别所对应的输出分量归一化,使分量的和为1,可以理解为output vector的输出分量值就是input data分类为每个类别的概率。
假设上面这个图中的 为一个三分类模型的output vector,为[3, 1, -3],分别代表类别1、类别2、类别3所对应的分量。经过Softmax函数作用后,将其转化为了 [0.88, 0.12, 0],代表输入的该样本被分到类别1的概率为0.88,分到类别2的概率为0.12,分到类别3的概率几乎为0。这就是 Softmax 函数的作用,Softmax 函数的表达式如下所示:
第二步:计算 Cross Entropy
神经网络的输出层经过Softmax函数作用后,接下来就要计算loss了,多分类使用Cross Entropy作为loss function。tf.nn.sparse_softmax_cross_entropy_with_logits() 函数输入的 label 格式是一维向量。Cross Entropy 的表达式如下所示:
其中: 为label中的第
个值,
为经 Softmax归一化输出的vector中的对应分量。当分类越准确时,
所对应的分量就会越接近于1,从而
的值也就会越小。
PS:如果 label 是 one-hot 格式,则可以使用 tf.nn.softmax_cross_entropy_with_logits() 函数来进行Softmax和loss的计算。
4. 示例 sparse_softmax_cross_entropy_with_logits
import tensorflow as tf
labels_sparse = [0, 2, 1]
# 索引,即真实的类别
# 0表示第一个样本的类别属于第1类;
# 2表示第二个样本的类别属于第3类;
# 1表示第三个样本的类别属于第2类;
logits = tf.constant(value=[[3, 1, -3], [1, 4, 3], [2, 7, 5]],
dtype=tf.float32, shape=[3, 3])
loss_sparse = tf.nn.sparse_softmax_cross_entropy_with_logits(
labels=labels_sparse,
logits=logits)
with tf.compat.v1.Session() as sess:
print("loss_sparse: \n", sess.run(loss_sparse))
结果如下所示:
loss_sparse:
[0.12910892, 1.3490121, 0.13284527]
根据计算步骤,使用第一个样本数据简单验证一下:
label_sparse = [0]
logit = tf.constant([3, 1, -3], dtype=tf.float64)
softmax_logit = tf.nn.softmax(logit)
softmax_cross_entropy_logit = -(tf.math.log(softmax_logit[label_sparse]))
with tf.compat.v1.Session() as sess:
print("softmax_cross_entropy_logit: \n", sess.run(softmax_cross_entropy_logit))
结果如下所示:
softmax_cross_entropy_logit:
0.1291089088298506
可知该值和 loss_sparse 的第一个值一致。
5. 示例 softmax_cross_entropy_with_logits
import tensorflow as tf
labels = [[1, 0, 0], [0, 0, 1], [0, 1, 0]]
# 索引,即真实的类别
# 0表示第一个样本的类别属于第1类;
# 2表示第二个样本的类别属于第3类;
# 1表示第三个样本的类别属于第2类;
logits = tf.constant(value=[[3, 1, -3], [1, 4, 3], [2, 7, 5]],
dtype=tf.float32, shape=[3, 3])
loss = tf.nn.softmax_cross_entropy_with_logits(
labels=labels,
logits=logits)
with tf.compat.v1.Session() as sess:
print("loss: \n", sess.run(loss))
结果如下所示:
loss:
[0.12910892, 1.3490121, 0.13284527]
根据结果可知,sparse_softmax_cross_entropy_with_logits 和 softmax_cross_entropy_with_logits 两种方式的计算结果是相同的。
6. 补充说明
使用 tf.keras.models.Model 构建好模型后,在 compile 的时候:
(1)如果:
loss='sparse_categorical_crossentropy'
则构建的样本的label是数字编码,同sparse_softmax_cross_entropy_with_logits中的 labels_sparse = [0, 2, 1]
(2)如果:
loss='categorical_crossentropy'
则构建的样本的label是one-hot编码,同 softmax_cross_entropy_with_logits中的 labels = [[1, 0, 0], [0, 0, 1], [0, 1, 0]]
参考:
1. https://tensorflow.google.cn/api_docs/python/tf/nn/sparse_softmax_cross_entropy_with_logits?hl=zh-cn
2. https://keras-cn-docs.readthedocs.io/zh_CN/latest/other/metrices/