1. 概述
学习Tensorflow关于交叉熵的计算方法时:
tf.nn.sparse_softmax_cross_entropy_with_logits
tf.nn.softmax_cross_entropy_with_logits
需要弄清楚这两个方法的差异,以及方法内部的细节,即这个方法是如何计算出来交叉熵的. 因此,使用一个具体的例子来说明.
上述两个方法有两个主要参数logits 和 labels. logits 是神经网络前向传播完成以后的计算结果.
注意 不要再logits上应用softmax.因为上面两个函数会使用更高效的方式计算softmax和cross entropy.
labels是训练数据的标签.
2. 实例
上面的两个计算交叉熵的方法一般用于单分类问题(一个图片只能属于一个类别)的损失函数.
假如有个图片识别问题,一张图片只可能属于狗,猫,兔之一,对于下面这个训练图片,其结果是猫,
因此这个训练数据的label格式为 0,1,0,而神经网络的前向传播计算结果logit可能为0.1, 0.8, 0.2.
综合上面的label和logit可得如下表格:
item
狗
猫
兔
label
0
1
0
logit
0.1
0.8
0.2
3. 计算公式
上面两个计算交叉熵的方法中,涉及到两个函数softmax和cross_entropy, 下面分别说明这两个函数的计算方法.
为简化说明,直接给出计算公式,避免用抽象的数学表达语言.
3.1. softmax
softmax 是将 数组[a, b, c] 变换成概率分布,假如转换完成后得到数组[A,B,C]满足:
A,B,C都在0和1之间,
且A+B+C=1成立
则A,B,C就是一种概率分布.
对于[a, b, c] 求softmax的公式为:
$$ softmax = \left[ \frac{e^a}{e^a + e^b + e^c}, \; \frac{e^b}{e^a + e^b + e^c}, \; \frac{e^c}{e^a + e^b + e^c} \right]$$
其中$e$是自然底数.
3.2. cross entropy
假设$label=[l_1,l_2,l_3]$, $logits=[a,b,c]$, 则交叉熵计算公式如下:
计算 logits 的 softmax $softmax([a,b,c]) = [S_a,S_b,S_c]$;
计算的softmax的对数(以$e$为底的 ) $log([S_a,S_b,S_c]) = [LS_a],LS_b,LS_c]$;
计算cross entropy $cross entropy = -(l_1 \times LS_a + l_2 \times LS_b + l_3 \times LS_c)$.
4. 代码实现
下面给出Python的实现代码, 以及和Tensorflow自带的方法的计算结果对比.
NOTE: 概述部分给出的两个函数的区别在于参数labels的形式. 假如labels=[0,1,0] 则sparse开头的方法,
传给labels参数的是数组([0,1,0])中1的位置,即1(从0开始的),这也是下面tf.argmax方法的功能.
因为sparse表示label是稀疏的,只有一个1,其他都是0,知道了1的位置就可以构造这个数组了.
#!/usr/bin/env python3
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import sklearn.datasets as skDs
import sklearn as skl
import tensorflow as tf_old
tf = tf_old.compat.v1
logit = [0.1, 0.8, 0.2]
label = [0, 1, 0]
def softmax(X):
total_exp = 0.0
xLen = len(X)
y = np.zeros(xLen)
for i in range(xLen):
exp = np.exp(X[i])
y[i] = exp
total_exp += exp
y = y / total_exp
return y
def cross_entropy(logit_, label_):
the_label = label_
current_output_softmax = softmax(logit_)
current_output_softmax_log = np.log(current_output_softmax)
result = - np.sum(the_label * current_output_softmax_log)
return result
def main():
y = tf.constant([logit])
y_ = tf.constant([label])
cross_entropy1 = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
cross_entropy2 = tf.nn.softmax_cross_entropy_with_logits(logits=y, labels=y_)
with tf.Session() as sess:
tf.global_variables_initializer().run()
print(sess.run(cross_entropy1))
print(sess.run(cross_entropy2))
if __name__ == '__main__':
main()
# main的输出结果为
# [0.7155919]
# [0.7155919]
print(cross_entropy(logit, label))
# 输出结果为 -0.7155918732927512
5. 参考链接
赞 赏
微信赞赏
支付宝赞赏