0 前言
tensorflow中自带四种交叉熵函数,tensorflow版本太低可能有的交叉熵函数没有,尽量版本高一些。
交叉熵计算输入的logits都不是softmax或sigmoid的输出,而是softmax或sigmoid函数的输入,也就是说在调用损失函数时会在内部进行sigmoid或softmax操作,直接喂给网络预测的输出值就可以了,而不能在调用函数前进行softmax或sigmoid,会导致计算会出错。
常用函数:
tf.nn.softmax_cross_entropy_with_logits()
tf.nn.sparse_softmax_cross_entropy_with_logits()
tf.nn.sigmoid_cross_entropy_with_logits()
tf.nn.weighted_cross_entropy_with_logits()
其次就是参数labels和logits的数据唯独、类型一定要按每个函数要求输入。可以在定义的时候指定或者调用交叉熵函数前转化。
-
定义时指定:
-
y = np.array([[0, 1, 0], [1, 0, 0]],dtype=float32) y_pre = np.array([[12, 3, 2], [3, 10, 1]],dtype=float32)
-
-
调用前转化:
-
y = np.array([[1, 0, 0], [0, 1, 0]],dtype=float32) y = np.array(y).astype(np.float32)
-
1 softmax 交叉熵
tf.nn.softmax_cross_entropy_with_logits(labels=, logits=)
tf.nn.softmax_cross_entropy_with_logits_v2(labels=Truth,logits=Pred_logits)
- logits:是NN网络计算的预测输出,维度是[batch_size, num_classes]
- labels:是标签,和logits 类型相同
- output:loss值,shape是[batch_size]
logits和labels数据类型和维度必须相同,float16, float32, or float64
文档解释如下:
logits and labels must have the same shape [batch_size, num_classes]
and the same dtype (either float16, float32, or float64).
高版本tf官方推荐使用第二个 V2,和第一个区别在于:
第一个只对logits进行反向传播,labels保持不变。第二个在进行反向传播的时候,同时对logits和labels都进行反向传播,如果将labels传入的tensor设置为stop_gradients,就和1一样了。
import numpy as np
import tensorflow as tf
y = np.array([[1, 0, 0], [0, 1, 0]],dtype=np.float32)
#y = np.array(y).astype(np.float32)
y_pre = np.array([[11, 4, 2], [4, 10, 2]],dtype=np.float32)
loss = tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=y_pre)
with tf.Session() as sess:
print(sess.run(loss))
'''
[ 0.00103468 0.00281022]
'''
2 sparse_softmax交叉熵
tf.nn.sparse_softmax_cross_entropy_with_logits(labels=None,logits=None)
- logits:计算的输出,shape是是[batch_size, num_classes],类型时float32、float64
- labels:shape是 [batch_size],类型必须为int32、int64
- output:loss值,shape是[batch_size]
logits参数和上面函数一样,labels可以不同,可以不是典型的one-hot多维数组形式,而直接是每组类别对应的数字,也可以是高维。文档如下。
labels of shape `[batch_size]`. But higher dimensions are supported
使用这个函数时,可以理解tf自动将类别[0,1,2,3,…numclass]转换成one_hot数组形式[[1,0,0,0,…],[0,1,0…],[0,0,1,0…]],然后比较计算交叉熵。
- 参数label是稀疏表示的,比如一个3分类样本的标签,非稀疏表示的形式为[0,0,1]这个表示这个样本为第3个分类,而稀疏表示就表示为2(从0开始,0,1,2,表示三类),同理[0,1,0]非稀疏表示为样本是第二类,而其稀疏表示为1。
y = np.array([0,1],dtype=np.int32)
y_pre = np.array([[11, 4, 2], [4, 10, 2]],dtype=np.float32)
loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=y_pre)
with tf.Session() as sess:
print(sess.run(loss))
'''
[ 0.00103468 0.00281022]
'''
3 sigmoid 交叉熵
labels和logits的维度和类型必须相同,float32或者float64
tf.nn.sigmoid_cross_entropy_with_logits(labels=, logits=)
- logits:计算的输出,shape:[batch_size, num_classes]
- labels:标签,同维度类型
- output:loss,shape是[batch_size,num_classes]
labels: A Tensor of the same type and shape as logits.
logits: A Tensor of type float32 or float64
对于输入的logits先通过sigmoid函数计算,再计算它们的交叉熵,但是它对交叉熵的计算方式进行了优化。
output不是每类对应的数,而是一个batch中每个样本的loss,所以一般配合tf.reduce_min(loss,axis=)使用。
y = np.array([[1, 0, 0], [0, 1, 0]],dtype=np.float32)
pre = np.array([[11, 4, 2], [4, 10, 2]],dtype=np.float32)
loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=y,logits=y_pre)
with tf.Session() as sess:
print(sess.run(loss))
'''
[[1.6701561e-05 4.0181499e+00 2.1269281e+00]
[4.0181499e+00 4.5398898e-05 2.1269281e+00]]
'''
sess = tf.Session()
a = sess.run(loss)
print(sess.run(tf.reduce_min(a,axis=1)))
‘’‘
[1.6701561e-05 4.5398898e-05]
’‘’
4 weighted交叉熵
有权重的sigmoid交叉熵sigmoid_cross_entropy_with_logits(),正负样本数量不均衡时使用。
标签和预测也需要同类型同维度
- logits and targets must have the same type and shape.
- float32 or float64
weighted_cross_entropy_with_logits(targets, logits, pos_weight, name=None)
- logits:shape为[batch_size,num_classes],单样本是[num_classes]
- targets:
- pos_weight:正样本的系数
- output:loss值,shape:[batch_size,num_classes]
输出的也是每一组batch的所有loss,需要配合tf.reduce_min(loss,axis=)筛选
sess.run(tf.nn.weighted_cross_entropy_with_logits(logits=y,targets=y_pre,pos_weight=2.0))
和sigmoid基本一样,就是多了个正样本权重。
使用过程中可以使用 help(函数名) 查看定义和如何使用。