Press "Enter" to skip to content

【深度学习】——损失函数(均方差损失和交叉熵损失)

损失函数在【机器学习基础】中有所提及,在深度学习中所使用最多的是均值平方差(MSE)和交叉熵(cross entropy)损失,这里着重介绍一下这两个损失函数及其在tensorflow中的实现。

 

1. 均方差损失

 

均方差就是预测值与真实值之间的差异,其公式为:

 

 

一般对于 标签是实数且无界的值 的时候,损失函数选用均方差损失。

 

均方差在tensorflow中的实现也比较简单:

 

MSE = tf.reduce_mean(tf.pow(tf.sub(logits, labels), 2.0))

 

MSE = tf.reduce_mean(tf.square(tf.sub(logits, labels)))

 

MSE = tf.reduce_mean(tf.square(logits, labels))

 

2. 交叉熵损失

 

交叉熵损失有 sigmoid交叉熵、softmax交叉熵、Sparse交叉熵、加权sigmoid交叉熵 。

 

2.1 sigmoid 交叉熵损失

 

对于sigmoid交叉熵,网络的输出值经过sigmoid函数,然后再与真实值计算交叉熵,但是由于sigmoid的映射是相互独立的,相加并不等于1。

 

因此,sigmoid对于二分类,最后的输出为一维的数值(LR算法),表明属于该类别的概率p,而不属于该类别的概率则为1-p;

 

而对于 多分类任务,输出的最后一维为m维,也就是m个类别,每一维表示属于该类别的概率,因此这里sigmoid将不再适用 。

 

对于多标签的分类,相当于多个二分类任务,最后一层输出为m维(m个标签),然后用sigmoid计算属于每个标签的概率,大于0.5则表明属于该标签。

 

在tensorflow中sigmoid交叉熵损失:

 

tf.nn.sigmoid_cross_entropy_with_logits(logits, labels, name=None)

 

logits为输出层的值,该值 没有经过simoid之前 ,labels为标签。

 

 

sigmoid交叉熵损失适用于每个类别相互独立但互不排斥的多标签分类问题 ,例如一幅图可以同时包含一条狗和一只大象。

 

output不是一个数,比如 5个样本三分类问题,且一个样本可以同时拥有多类,一个样本会在每个类别上有一个交叉熵,输出也就是5*3矩阵。

 

y = np.array([[1,  0,  0], 
              [0,  1,  0], 
              [0,  0,  1], 
              [1,  1,  0], 
              [0,  1,  0]])
logits = np.array([[12,  3,  2], 
                   [3,  10,  1], 
                   [1,  2,  5], 
                   [4,  6.5,  1.2], 
                   [3,  6,  1]])
y_pred = sigmoid(logits)
E1 = -y * np.log(y_pred)- (1-y) * np.log(1-y_pred)
print(E1)
sess = tf.Session()
y = np.array(y).astype(np.float64) # labels是float64的数据类型
E2 = sess.run(tf.nn.sigmoid_cross_entropy_with_logits(labels=y,logits=logits))
print(E2)
# output:E1 = E2
[[6.14419348e-06     3.04858735e+00    2.12692801e+00]
 [3.04858735e+00    4.53988992e-05     1.31326169e+00]
 [1.31326169e+00    2.12692801e+00     6.71534849e-03]
 [1.81499279e-02    1.50231016e-03      1.46328247e+00]
 [3.04858735e+00    2.47568514e-03     1.31326169e+00]]

 

2.2 softmax 交叉熵损失

 

softmax交叉熵 是最常用的一种损失函数, 适用于多分类的问题 ,在手写数字识别中每个数字只可能属于某一个类别。

 

经softmax层后输出m维,表示m个类别,这m个值相加等于1,表示属于某一个类别的概率。

 

softmax交叉熵损失在tensorflow中定义:

 

tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)

 

跟sigmoid交叉熵一样,这里的 logits都是没有经过对应的softmax之前的那一层输出 。

 

如果经过了softmax层,然后再计算交叉熵也是可以的:

 

# 最后一层的网络输出result
# 经过一层softmax
result1 = tf.nn.softmax(result)
# 通过result1计算交叉熵
cross_entropy = -tf.reduce_sum(labels * tf.log(result1), 1)

 

上面的方法与softmax_cross_entropy_with_logits得到的结果是一致的。

 

对于softmax交叉熵, 一个样本所得到的交叉熵就是一个值 ,一个batch_size的交叉熵就有batch_size个值,因此最后还要 进一步加和求loss :

 

loss = tf.reduce_sum(tf.nn.softmax_cross_entropy_with_logits(logits, labels))

 

等价于:

 

loss = tf.reduce_sum(-tf.reduce_sum(labels * tf.log(result1), 1))

 

2.3 Sparse 交叉熵损失

 

Sparse交叉熵损失是用于非ont_hot编码的标签,也就是标签变成了具体的数值,比如对于多分类ont_hot标签【0,0,1】,那幺Sparse中对应的标签为数值2。

 

在tensorflow中处理这样的问题使用:

 

tf.nn.sparse_corss_entropy_with_logits(logits, labels)

 

这个函数会将传入的非one-hot标签转成one-hot标签,所以它的计算方式与softmax相同,而且适用于多分类的情况,一般情况为了避免不必要的麻烦,不经常使用这个方法,还是直接在处理数据时one-hot。

 

logits = [[2,  0.5,6],
          [0.1,0,  3]]
labels = [2,1]
result = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels, logits=logits)

 

2.4 总结

 

1、对于二分类情况,通常sigmoid交叉熵和softmax交叉熵损失均可使用,只是使用的方式不同,sigmoid是一个一维的值,softmax是二维的;

 

2、sigmoid交叉熵损失适用于多标签分类问题,如一张图片中既有猫,又有狗;

 

3、softmax交叉熵损失和Sparse交叉熵损失适用于多分类问题

 

 

参考资料:

 

【深度学习理论】一文搞透sigmoidsoftmax交叉熵/l1/l2/smooth l1 loss

 

交叉熵和softmax函数和sigmoid函数(在二分类中的比较)

 

sigmoid交叉熵和softmax交叉熵的区别

 

这两种是深度学习中最常用的损失函数,因此这里只对这两种做一个简单的介绍,主要交叉熵在调用的时候容易出错,这里做一个记录。

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注