关于categorical cross entropy 和 binary cross entropy的比较,差别通常体如今不一样的分类(二分类、多分类等)任务目标,能够参考文章keras中两种交叉熵损失函数的探讨,其结合keras的API讨论了二者的计算原理和应用原理。python
本文主要是介绍TF中的接口调用方式。git
对应的是网络输出单个节点,这个节点将被sigmoid处理,使用阈值分类为0或者1的问题。此类问题logits和labels必须具备相同的type和shape。网络
设x = logits
, z = labels
.
logistic loss 计算式为: 其中交叉熵(cross entripy)基本函数式dom
z * -log(sigmoid(x)) + (1 - z) * -log(1 - sigmoid(x))
= z * -log(1 / (1 + exp(-x))) + (1 - z) * -log(exp(-x) / (1 + exp(-x)))
= z * log(1 + exp(-x)) + (1 - z) * (-log(exp(-x)) + log(1 + exp(-x)))
= z * log(1 + exp(-x)) + (1 - z) * (x + log(1 + exp(-x))
= (1 - z) * x + log(1 + exp(-x))
= x - x * z + log(1 + exp(-x))函数
对于x<0时,为了不计算exp(-x)时溢出,咱们使用如下这种形式表示学习
x - x * z + log(1 + exp(-x))
= log(exp(x)) - x * z + log(1 + exp(-x))
= - x * z + log(1 + exp(x))spa
综合x>0和x<0的状况,并防止溢出咱们使用以下公式,code
max(x, 0) - x *z + log(1 + exp(-abs(x)))对象
import numpy as np import tensorflow as tf input_data = tf.Variable(np.random.rand(1, 3), dtype=tf.float32) # np.random.rand()传入一个shape,返回一个在[0,1)区间符合均匀分布的array output = tf.nn.sigmoid_cross_entropy_with_logits(logits=input_data, labels=[[1.0, 0.0, 0.0]]) with tf.Session() as sess: init = tf.global_variables_initializer() sess.run(init) print(sess.run(output)) # [[ 0.5583781 1.06925142 1.08170223]]
对应的是网络输出多个节点,每一个节点表示1个class的得分,使用Softmax最终处理的分类问题。blog
cross_entropy = -tf.reduce_mean(y * tf.log(tf.clip_by_value(y_pre, 1e-10, 1.0))
调用一下:
import tensorflow as tf input_data = tf.Variable([[0.2, 0.1, 0.9], [0.3, 0.4, 0.6]], dtype=tf.float32) labels=tf.constant([[1,0,0], [0,1,0]], dtype=tf.float32) cross_entropy = -tf.reduce_mean(labels * tf.log(tf.clip_by_value(input_data, 1e-10, 1.0))) with tf.Session() as sess: init = tf.global_variables_initializer() sess.run(init) print(sess.run(output))
softmax以后,计算输出层所有节点各自的交叉熵(输出向量而非标量)
cross_entropy_mean = tf.reduce_mean( tf.nn.sparse_softmax_cross_entropy_with_logits( labels=tf.argmax(labels,1), logits=logits), name='cross_entropy') cross_entropy_mean = tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits( logits=logits, labels=labels), name='cross_entropy')
函数的参数label是稀疏表示的,好比表示一个3分类的一个样本的标签,稀疏表示的形式为[0,0,1]这个表示这个样本为第3个分类,而非稀疏表示就表示为2,同理[0,1,0]就表示样本属于第2个分类,而其非稀疏表示为1。
import tensorflow as tf input_data = tf.Variable([[0.2, 0.1, 0.9], [0.3, 0.4, 0.6]], dtype=tf.float32) output = tf.nn.softmax_cross_entropy_with_logits(logits=input_data, labels=[[1,0,0], [0,1,0]]) with tf.Session() as sess: init = tf.global_variables_initializer() sess.run(init) print(sess.run(output))
此函数大体与tf.nn.softmax_cross_entropy_with_logits的计算方式相同,
适用于每一个类别相互独立且排斥的状况,一幅图只能属于一类,而不能同时包含一条狗和一只大象
可是在对于labels的处理上有不一样之处,labels从shape来讲此函数要求shape为[batch_size],
labels[i]是[0,num_classes)的一个索引, type为int32或int64,即labels限定了是一个一阶tensor,
而且取值范围只能在分类数以内,表示一个对象只能属于一个类别
import tensorflow as tf input_data = tf.Variable([[0.2, 0.1, 0.9], [0.3, 0.4, 0.6]], dtype=tf.float32) output = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=input_data, labels=[0, 2]) with tf.Session() as sess: init = tf.global_variables_initializer() sess.run(init) print(sess.run(output)) # [ 1.36573195 0.93983102]
比tf.nn.softmax_cross_entropy_with_logits多了一步将labels稀疏化的操做。由于深度学习中,图片通常是用非稀疏的标签的,因此tf.nn.sparse_softmax_cross_entropy_with_logits()的频率比tf.nn.softmax_cross_entropy_with_logits高。
不过二者输出尺寸等于输入shape去掉最后一维(上面输入[2*3],输出[2]),因此均常和tf.reduce_mean()连用。