TensorFlow 中的 Loss 函数介绍

TensorFlow 中的 Loss 函数介绍

前言

TensorFlow 提供了很多计算 Loss 的 API, 很多时候容易忘记这些 API 的输入和输出的 Shape. 这里对经常用到的 API 做个记录, 并配上 API 的使用实例, 加深体会.

广而告之

可以在微信中搜索 “珍妮的算法之路” 或者 “world4458” 关注我的微信公众号;另外可以看看知乎专栏 PoorMemory-机器学习, 以后文章也会发在知乎专栏中;

softmax_cross_entropy_with_logits

tf.nn.softmax_cross_entropy_with_logits 用于分类问题计算交叉熵, 输入分别是 labelslogits (logits 是神经网络的输出结果, 但还未输入到 tf.nn.softmax 方法中; labels 一般是 OneHot 的形式, 可以使用 tf.one_hot). 下面看个例子:

import os
import tensorflow as tf

os.environ['TF_CPP_MIN_LOG_LEVEL']='3'
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'

logits = tf.constant([[1.0,2.0,3.0],
                      [1.0,2.0,3.0],
                      [1.0,2.0,3.0]])
y_ = tf.constant([[0.0,0.0,1.0],
                  [0.0,0.0,1.0],
                  [0.0,0.0,1.0]])

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

logits = tf.nn.softmax(logits)
manual_loss = tf.reduce_sum(-y_ * tf.log(tf.clip_by_value(logits, 1e-10, 1.)), axis=1)

with tf.Session() as sess:
    loss_, logits_, manual_loss_ = sess.run([loss, logits, manual_loss])
    print('loss: {}'.format(loss_))
    print('logits_: {}'.format(logits_))
    print('manual_loss_: {}'.format(manual_loss_))
    
### -----------------输出结果 --------------------------
loss_:    [0.40760595 0.40760595 0.40760595]
logits_: [[0.09003057 0.24472848 0.66524094]
          [0.09003057 0.24472848 0.66524094]
          [0.09003057 0.24472848 0.66524094]]
manual_loss_: [0.407606   0.407606   0.40760598]

可以看到

  • loss_manual_loss_ 的结果是一致的 (请忽略些许的误差).
  • 如果输入的 logits 的 Shape 为 (B, T), 那么 labels 变换成 OneHot 的形式, 大小也为 (B, T).
  • logitslabels 输入到 tf.nn.softmax_cross_entropy_with_logits 后, 得到的结果是 (B,); 因此, 在实践中, 为了得到一个 Batch 的平均 loss, 需要使用:
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y_))
  • manual_loss_ 的计算方式: l o s s = ∑ j = 1 T y j ⋅ log ⁡ ( y ^ j ) loss = \sum\limits_{j=1}^{T} y_j\cdot\log(\hat{y}_j) loss=j=1Tyjlog(y^j), 其中 y j ∈ { 0 , 1 } y_j\in\{0, 1\} yj{ 0,1}.

sparse_softmax_cross_entropy_with_logits

softmax_cross_entropy_with_logits 不同的是, labels 无需变换成 OneHot 的形式. 还是拿上面的作为例子, 代码只需要对 labels 做一定修改即可.

import os
import tensorflow as tf

os.environ['TF_CPP_MIN_LOG_LEVEL']='3'
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'

logits = tf.constant([[1.0,2.0,3.0],
                      [1.0,2.0,3.0],
                      [1.0,2.0,3.0]])
y = tf.constant([2, 2, 2], dtype=tf.int32) # 和上一节的代码相比, 注意此处的改动

loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=y)

logits = tf.nn.softmax(logits)
y_ = tf.one_hot(y, depth=3)  ## 注意此处的改动
manual_loss = tf.reduce_sum(-y_ * tf.log(tf.clip_by_value(logits, 1e-10, 1.)), axis=1)

with tf.Session() as sess:
    loss_, logits_, manual_loss_ = sess.run([loss, logits, manual_loss])
    print('loss_: {}'.format(loss_))
    print('logits_: {}'.format(logits_))
    print('manual_loss_: {}'.format(manual_loss_))

### -----------------输出结果 --------------------------
loss_:   [0.40760595 0.40760595 0.40760595]
logits_: [[0.09003057 0.24472848 0.66524094]
          [0.09003057 0.24472848 0.66524094]
          [0.09003057 0.24472848 0.66524094]]
manual_loss_: [0.407606   0.407606   0.40760598]

猜你喜欢

转载自blog.csdn.net/Eric_1993/article/details/108066733