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


    损失函数在【机器学习基础】中有所提及,在深度学习中所使用最多的是均值平方差(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交叉熵的区别


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

  • 相关阅读:
    Framwork入门のPiex 6P源码(下载/编译/刷机)
    玩转字符串——不一样的风格
    透过等待看数据库
    Thread线程异常的处理方式
    银行卡号识别
    Http请求get与post请求方式的各种相关面试总结
    Ubuntu18.04安装protobuf
    微信小程序使用 MoxB 实现全局状态管理
    解决IP查询结果偏差的几个方法
    react 使用useRoutes遇到的问题
  • 原文地址:https://www.cnblogs.com/501731wyb/p/16647320.html