gpt4 book ai didi

python - softmax 的 Tensorflow 问题

转载 作者:行者123 更新时间:2023-12-04 11:53:34 25 4
gpt4 key购买 nike

我有一个生成 nan 的 Tensorflow 多类分类器或 inf使用 tf.nn.softmax 计算概率时.请参阅以下代码段( logits 的形状为 batch_size x 6 ,因为我有 6 个类并且输出是单热编码的)。 batch_size是 1024。

logits = tf.debugging.check_numerics(logits, message='bad logits', name=None)
probabilities = tf.nn.softmax(logits=logits, name='Softmax')
probabilities = tf.debugging.check_numerics(probabilities, message='bad probabilities', name=None)
分类器在最后一条语句上失败,因为它找到了 naninfprobabilities . logits是干净的,否则第一个语句将失败。
从我读到的 tf.nn.softmax ,它可以处理 logits 中非常大和非常小的值。我已经在交互模式下验证了这一点。
>>> with tf.Session() as s:
... a = tf.constant([[1000, 10], [-100, -200], [3, 4.0]])
... sm = tf.nn.softmax(logits=a, name='Softmax')
... print(a.eval())
... print(sm.eval())
...
[[1000. 10.]
[-100. -200.]
[ 3. 4.]]
[[1. 0. ]
[1. 0. ]
[0.26894143 0.7310586 ]]
然后我尝试裁剪 logits 中的值现在整个事情都在起作用了。请参阅下面的修改后的片段。
logits = tf.debugging.check_numerics(logits, message='logits', name=None)
safe_logits = tf.clip_by_value(logits, -15.0, 15.0)
probabilities = tf.nn.softmax(logits=safe_logits, name='Softmax')
probabilities = tf.debugging.check_numerics(probabilities, message='bad probabilities', name=None)
在第二个语句中,我正在裁剪 logits 中的值到 -15 和 15,这以某种方式阻止了 nan/ inf在 softmax 计算中。所以,我能够解决手头的问题。
但是,我仍然不明白为什么这种剪辑会起作用? (我应该提到 -20 和 20 之间的裁剪不起作用并且模型失败, naninf in probabilities )。
有人能帮我理解为什么会这样吗?
我正在使用 tensorflow 1.15.0,在 64 位实例上运行。

最佳答案

首先要看的是值(value)观本身,你已经这样做了。第二个要看的地方是渐变。即使值看起来合理,如果梯度非常陡峭,反向传播最终会爆炸梯度和值。
例如,如果 logits 是由 log(x) 之类的东西生成的,则 x 为 0.001 将生成 -6.9。看起来很良心。但是梯度是1000!这将在反向传播/正向传播期间迅速爆炸梯度和值。

# Pretend this is the source value that is fed to a function that generates the logit. 
>>> x = tf.Variable(0.001)

# Let's operate on the source value to generate the logit.
>>> with tf.GradientTape() as tape:
... y = tf.math.log(x)
...

# The logit looks okay... -6.9.
>>> y
<tf.Tensor: shape=(), dtype=float32, numpy=-6.9077554>

# But the gradient is exploding.
>>> tape.gradient(y,x)
<tf.Tensor: shape=(), dtype=float32, numpy=999.99994>
>>>
裁剪 logit 似乎专注于生成较小的值以提供给 softmax,但这可能不是它有帮助的原因。 (事实上​​,softmax 可以处理值为 tf.float32.max 的 logit 没问题,所以 logit 的值不太可能是问题所在)。可能真正发生的情况是,当您剪辑到 15 时,您还将梯度设置为零,否则 logit 将是 20,并且具有爆炸性梯度。因此裁剪该值也会引入裁剪渐变。
# This is same source variable as above. 
>>> x = tf.Variable(0.001)

# Now let's operate with clipping.
>>> with tf.GradientTape() as tape:
... y = tf.clip_by_value(tf.math.log(x), -1., 1.)
...

# The clipped logit still looks okay...
>>> y
<tf.Tensor: shape=(), dtype=float32, numpy=-1.0>

# What may be more important is that the clipping has also zeroed out the gradient
>>> tape.gradient(y,x)
<tf.Tensor: shape=(), dtype=float32, numpy=0.0>

关于python - softmax 的 Tensorflow 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68988859/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com