【问题标题】:Why the gradient of categorical crossentropy loss with respect to logits is 0 with gradient tape in TF2.0?为什么在 TF2.0 中使用梯度带,分类交叉熵损失相对于 logits 的梯度为 0?
【发布时间】:2020-01-13 11:48:37
【问题描述】:

我正在学习 Tensorflow 2.0,并试图弄清楚渐变磁带的工作原理。我有一个简单的例子,在这个例子中,我评估了 logits 和标签之间的交叉熵损失。我想知道为什么相对于 logits 的梯度为零。 (请看下面的代码)。 TF的版本是tensorflow-gpu==2.0.0-rc0。

logits = tf.Variable([[1, 0, 0], [1, 0, 0], [1, 0, 0]], type=tf.float32)
labels = tf.constant([[1, 0, 0], [0, 1, 0], [0, 0, 1]],dtype=tf.float32)
with tf.GradientTape(persistent=True) as tape:
    loss = tf.reduce_sum(tf.losses.categorical_crossentropy(labels, logits))

grads = tape.gradient(loss, logits)
print(grads)

我得到了

 tf.Tensor(
[[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]], shape=(3, 3), dtype=float32)

结果,但它不应该告诉我应该更改多少 logits 以最小化损失吗?

【问题讨论】:

    标签: tensorflow gradient


    【解决方案1】:

    计算交叉熵损失时,在tf.losses.categorical_crossentropy()中设置from_logits=True。默认为 false,这意味着您直接使用-p*log(q) 计算交叉熵损失。通过设置from_logits=True,您正在使用-p*log(softmax(q)) 来计算损失。

    更新:

    只要找到一个有趣的结果。

    logits = tf.Variable([[0.8, 0.1, 0.1]], dtype=tf.float32)
    labels = tf.constant([[1, 0, 0]],dtype=tf.float32)
    
    with tf.GradientTape(persistent=True) as tape:
        loss = tf.reduce_sum(tf.keras.losses.categorical_crossentropy(labels, logits, from_logits=False))
    
    grads = tape.gradient(loss, logits)
    print(grads)
    

    毕业生将是tf.Tensor([[-0.25 1. 1. ]], shape=(1, 3), dtype=float32)

    之前,我认为 tensorflow 会使用loss=-\Sigma_i(p_i)\log(q_i) 来计算损失,如果我们在q_i 上推导,我们将得到导数是-p_i/q_i。所以,预期的毕业生应该是[-1.25, 0, 0]。但是输出的grads看起来都增加了1。但这不会影响优化过程。

    目前,我仍在试图弄清楚为什么毕业生人数会增加一。看了tf.categorical_crossentropy的源码后发现,即使我们设置了from_logits=False,它还是归一化了概率。这将改变最终的梯度表达式。具体来说,渐变将是-p_i/q_i+p_i/sum_j(q_j)。如果p_i=1sum_j(q_j)=1,最终的梯度将加一。这就是为什么渐变会是-0.25,但是,我还没弄清楚为什么最后两个渐变会是1.

    证明所有梯度都增加了1/sum_j(q_j)

    logits = tf.Variable([[0.5, 0.1, 0.1]], dtype=tf.float32)
    labels = tf.constant([[1, 0, 0]],dtype=tf.float32)
    
    with tf.GradientTape(persistent=True) as tape:
        loss = tf.reduce_sum(tf.keras.losses.categorical_crossentropy(labels, logits, from_logits=False))
    
    grads = tape.gradient(loss, logits)
    print(grads)
    

    毕业生是tf.Tensor([[-0.57142866 1.4285713 1.4285713 ]],应该是[-2,0,0]

    显示所有梯度都增加了1/(0.5+0.1+0.1)。对于p_i==1,渐变增加1/(0.5+0.1+0.1) 对我来说是有意义的。但是不明白为什么p_i==0,渐变还是增加了1/(0.5+0.1+0.1)

    【讨论】:

    • 谢谢。我注意到它是这样工作的。但是,为什么from_logits=False 仍然不能工作?
    • 嗨@Siavash,请检查我的更新。我仍在试图找出这种奇怪的行为。
    猜你喜欢
    • 2020-01-17
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 2020-08-07
    • 1970-01-01
    • 2017-11-16
    • 2018-10-22
    • 2020-02-29
    相关资源
    最近更新 更多