首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >softmax的Tensorflow问题

softmax的Tensorflow问题
EN

Stack Overflow用户
提问于 2021-08-30 18:35:38
回答 1查看 296关注 0票数 6

我有一个Tensorflow多类分类器,它在使用tf.nn.softmax计算概率的同时生成naninf。请看下面的代码片段(logits的形状是batch_size x 6,因为我有6个类,并且输出是单热编码的)。batch_size是1024。

代码语言:javascript
复制
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)

分类器在最后一条语句中失败,因为它在probabilities中找到naninflogits是干净的,否则第一条语句就会失败。

根据我所读到的关于tf.nn.softmax的内容,它可以处理logit中的非常大和非常小的值。我已经在交互模式中验证了这一点。

代码语言:javascript
复制
>>> 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中裁剪这些值,现在整个过程都正常了。请参阅下面修改后的代码片段。

代码语言:javascript
复制
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,这以某种方式阻止了softmax计算中的nan/inf。因此,我能够解决手头的问题。

然而,我仍然不明白为什么这个剪辑是有效的?(我应该指出的是,在-20和20之间的裁剪不起作用,并且在probabilities中使用naninf时模型会失败)。

有没有人能告诉我为什么会这样?

我使用的是tensorflow 1.15.0,在一个64位实例上运行。

EN

回答 1

Stack Overflow用户

发布于 2021-09-02 19:23:38

首先要查看的是值本身,您已经这样做了。第二个要看的地方是梯度。即使这个值看起来很合理,如果梯度非常陡峭,backprop最终也会爆炸梯度和值。

例如,如果logits是由log(x)之类的东西生成的,则x为0.001将生成-6.9。看起来很良性。但是梯度是1000!这将在backprop / forward prop过程中快速爆炸梯度和值。

代码语言:javascript
复制
# 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.float at32.max的logit,所以不太可能是logit的值有问题)。真正可能发生的情况是,当你修剪到15时,你也将梯度设置为零,否则logit将以爆炸性的梯度设置为20。因此,修剪该值也会引入修剪的渐变。

代码语言:javascript
复制
# 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>
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68988859

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档