代码之家  ›  专栏  ›  技术社区  ›  StatsNoob

带tf的张量流梯度。NaN本不应该返回的地方

  •  1
  • StatsNoob  · 技术社区  · 7 年前

    以下是可复制代码。如果您运行它,您将看到在第一次sess运行中,结果是nan,而第二种情况给出了正确的渐变值0.5。但根据tf。如果指定了和条件,则它们应返回相同的值。我也不明白为什么tf。其中,函数梯度为nan,为1或-1,这对我来说似乎是非常好的输入值。

    tf.reset_default_graph()
    x = tf.get_variable('x', shape=[1])
    condition = tf.less(x, 0.0)
    output = tf.where(condition, -tf.log(-x + 1), tf.log(x + 1))
    deriv = tf.gradients(output, x)
    with tf.Session() as sess:
        print(sess.run(deriv, {x:np.array([-1])}))
    
    logg = -tf.log(-x+1)
    derivv = tf.gradients(logg, x)
    with tf.Session() as sess:
        print(sess.run(derivv, {x:np.array([-1])}))
    

    感谢您的评论!

    1 回复  |  直到 7 年前
        1
  •  2
  •   P-Gn    7 年前

    如中所述 github issue 由@mikkola提供,问题源于 tf.where .基本上,两个备选方案(及其梯度)都是计算出来的,只有正确的部分是通过条件乘法选择的。唉,如果梯度是 inf nan 对于以下部分 选中,即使乘以0,也会得到 南安 最终传播到结果。

    自2016年5月发布以来(即tensorflow v0.7!)由于没有修补,人们可以放心地认为这不会很快出现,并开始寻找解决方法。

    最简单的修复方法是修改语句,使它们始终有效且可微,即使对于不打算选择的值也是如此。

    一般的技术是将输入值裁剪到其有效域内。因此,以您的情况为例,您可以使用

    cond = tf.less(x, 0.0)
    output = tf.where(cond,
      -tf.log(-tf.where(cond, x, 0) + 1),
      tf.log(tf.where(cond, 0, x) + 1))
    

    但是,在您的特定情况下,仅使用

    output = tf.sign(x) * tf.log(tf.abs(x) + 1)