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

1. 均方差损失

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

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

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

  均方差在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为标签。

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

  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交叉熵损失适用于多分类问题

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

参考资料:

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

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

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


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

09-06 12:38