对batch求算loss时loss是张量形式或是标量有什么不同?

  • 一般情况下我们使用一个batch的数据计算出一个平均的loss,再使用这个loss反向传播求得模型参数的梯度并更新,例如:

    loss = tf.reduce_mean(y - y_pred)	# 文中y和y_pred的shape均为:[b, 1],其中b是batch_size.
    

    这种情况比较好理解,loss只是一个值,其反向传播时对于每个参数也值计算出一个梯度值。

  • 而如果我们没有使用tf.reduce_mean()等类似求平均的操作,即:

    loss = y - y_pred
    

    求出的loss其shape是[b, 1]。即batch中的每一个样本都有一个对应的loss值。这个时候如果我们继续调用:

    grads = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(zip(grads, model.trainable_variables))
    

    也不会报错,不禁让人疑惑这个tape.gradient()是怎么处理loss不是标量值的情况的。

  • 先说结论:当loss不是单值时tape.gradient(loss, variables)会首先针对loss中每一个单值对variables求梯度得到多套梯度。再对每套梯度对应元素求和合并为一套梯度返回。

  • 验证:
    image
    image

  • 其他补充

    • tf.keras.losses.BinaryCrossentopy等大写字母开头的损失类在我们传入y, y_pred时会自动对所有样本的loss求平均,其返回一个标量的loss。
    • tf.keras.losses.binary_crossentropy()等小写字母开头的函数式接口在我们传入y, y_pred时不会对所有样本的loss求平均,其返回一个张量形式的losses,维度为[batch, 1]。
posted @ 2021-11-07 13:51  风和雨滴  阅读(1598)  评论(0编辑  收藏  举报