tensorflow中常见的损失函数

今天在构建一个卷积网络时看到书上例程里用的tf.nn.sparse_softmax_cross_entropy_with_logits()这个函数,打开Documentation看了没太明白,特地讲三种常见的loss function归纳总结下。

1、对数概率logit

首先解释什么是logit.

我们在学ML时一开始都是使用线性模型进行回归学习,其实线性模型也可以进行分类:对给定数据集(X, Y),我们想要对Y进行二分类,用线性模型得到w*x+b取值是连续的,不能来表示输出y,但是我们可以用它来拟合p(y=1/x)p(y=0/x). 又(w*x+b)\in (-\infty ,+\infty ), 不合符概率取值[0,1], 因此构造对数概率函数(logiitic function): 

                                           P(y=1/\vec{x})=1/(1+e^{-z}) ,z=\vec{w}*\vec{x}+b

又 P(y=0/\vec{x})=1-P(y=1/\vec{x}) , 则 ln(P(y=1/\vec{x})/P(y=0/\vec{x}))=z=\vec{w}*\vec{x}+b 即

                                           L(p)=ln\frac{p}{1-p}

反映了样本作为正例的相对可能性。它可以将取值范围在[0,1]内的概率映射到实数域[-inf,inf]的函数,如果p=0.5,函数值为0;p<0.5,函数值为负;p>0.5,函数值为正。

相对地,softmax和sigmoid则都是将[-inf,inf]映射到[0,1]的函数。

在tensorflow里,函数的形参如果是"logits",指该方法是在logit数值上使用softmax或者sigmoid来进行normalization的,也暗示用户不需要将网络输出自己再进行sigmoid或者softmax,这些过程可以在函数内部更高效地计算。

2、tf.nn.sigmoid_cross_entropy_with_logits

sigmoid_cross_entropy_with_logits(
    _sentinel=None,
    labels=None,
    logits=None,
    name=None
)

该网络会计算logits和labels的sigmoid cross entropy loss并返回,衡量独立不互斥离散分类任务的误差,说独立不互斥离散分类任务是因为,在这些任务中类与类之间是独立但是不互斥的,拿多分类任务中的多目标检测来举例子,一张图中可以有各种instance,比如有一只狗和一只猫。对于一个总共有五类的多目标检测任务,假如网络的输出层有5个节点,label的形式是[1,1,0,0,1]这种,1表示该图片有某种instance,0表示没有。那么,每个instance在这张图中有没有这显然是独立事件,但是多个instance可以存在一张图中,这就说明事件们并不是互斥的。所以我们可以直接将上一层网络的输出用作该方法的logits输入,从而进行输出与label的cross entropy loss。

更加直白的来说,这种网络的labels不需要进行one hot处理。不同于softmax系列函数是张量中向量与向量间的运算。sigmoid_cross_entropy_with_logits函数则是张量中标量与标量间的运算。 剖开函数内部,因为labels和logits的形状都是[batch_size, num_classes],那么如何计算他们的交叉熵呢,毕竟它们都不是有效的概率分布(一个batch内输出结果经过sigmoid后和不为1)。因为它的loss的计算是element-wise的,方法返回的loss的形状和labels是相同的,也是[batch_size, num_classes],再调用reduce_mean方法计算batch内的平均loss。所以这里的cross entropy其实是一种class-wise的cross entropy,每一个class是否存在都是一个事件,对每一个事件都求cross entropy loss,再对所有的求平均,作为最终的loss。

3、tf.nn.softmax_cross_entropy_with_logits

softmax_cross_entropy_with_logits(
    _sentinel=None,
    labels=None,
    logits=None,
    dim=-1,
    name=None
)

该网络会计算logits和labels的softmax cross entropy loss,衡量独立互斥离散分类任务的误差,说独立互斥离散分类任务是因为,在这些任务中类与类之间是独立而且互斥的,比如VOC classification、Imagenet、CIFAR-10甚至MNIST,这些都是多分类任务,但是一张图就对应着一个类,class在图片中是否存在是独立的,并且一张图中只能有一个class,所以是独立且互斥事件。

该函数要求每一个label都是一个有效的概率分布,对于Imagenet中的ILSVRC2012这种任务,那么label应该就对应一个one hot编码,ILSVRC2012提供的数据集中一共有1000个类,那么label就应该是一个1x1000的vector,形式为[0,0,...,1,0,....0],1000个元素中有且只有一个元素是1,其余都是0。

要求labels的形式为one hot是因为网络的输出要进行softmax,得到的就是一个有效的概率分布,这里不同与sigmoid,因为sigmoid并没有保证网络所有的输出经过sigmoid后和为1,不是一个有效的概率分布。

有了labels和softmax后的logits,就可以计算交叉熵损失了,最后得到的是形状为[batch_size, 1]的loss。

4、tf.nn.sparse_softmax_cross_entropy_with_logits

sparse_softmax_cross_entropy_with_logits(
    _sentinel=None,
    labels=None,
    logits=None,
    name=None
)

这个版本是tf.nn.softmax_cross_entropy_with_logits的易用版本,这个版本的logits的形状依然是[batch_size, num_classes],但是labels的形状是[batch_size, 1],不需要进行one hot编码,每个label的取值是从[0, num_classes)的离散值,这也更加符合我们的使用习惯,是哪一类就标哪个类对应的label。

输出的loss形状也是[batch_size, 1].

5、总结:

到底是用sigmoid版本的cross entropy还是softmax版本的cross entropy主要取决于我们模型的目的,以及label的组织方式,这个需要大家在使用的时候去揣摩,到底使用哪一种loss比较合理。

注:tensorflow的cross_entropy系列函数求交叉熵时用的都是以 e 为底的对数。

猜你喜欢

转载自blog.csdn.net/fang_chuan/article/details/87866512