【问题标题】:Tensorflow neural network loss value NaNTensorFlow 神经网络损失值 NaN
【发布时间】:2017-10-19 06:39:49
【问题描述】:

我正在尝试在大型数据集上构建一个简单的多层感知器模型,但我得到的损失值为 nan。奇怪的是:在第一个训练步骤之后,损失值不是 nan,而是大约 46(这是奇怪的低。当我运行逻辑回归模型时,第一个损失值大约是 ~3600)。但是,在那之后,损失值一直是 nan。我也使用 tf.print 来尝试调试它。

该模型的目标是预测约 4500 个不同的类别 - 所以这是一个分类问题。使用 tf.print 时,我看到在第一个训练步骤(或通过 MLP 前馈)之后,来自最后一个全连接层的预测似乎是正确的(所有在 1 和 4500 之间变化的数字)。但是,在那之后,最后一个全连接层的输出要么全为 0,要么变为其他常数(0 0 0 0 0)。

关于我的模型的一些信息:

  • 3 层模型。所有全连接层。

  • 批量大小为 1000

  • 0.001 的学习率(我也尝试了 .1 和 .01,但没有任何改变)

  • 使用 CrossEntropyLoss(我确实添加了一个 epsilon 值来防止 log0)

  • 使用 AdamOptimizer

  • 学习率衰减为 0.95

模型的具体代码如下:(我使用的是 TF-Slim 库)

input_layer = slim.fully_connected(model_input, 5000, activation_fn=tf.nn.relu)
hidden_layer = slim.fully_connected(input_layer, 5000, activation_fn=tf.nn.relu)
output = slim.fully_connected(hidden_layer, vocab_size, activation_fn=tf.nn.relu)
output = tf.Print(output, [tf.argmax(output, 1)], 'out = ', summarize = 20, first_n = 10)
return {"predictions": output}

任何帮助将不胜感激!非常感谢!

【问题讨论】:

    标签: python tensorflow neural-network loss tf-slim


    【解决方案1】:

    它不起作用的两个(可能更多)原因:

    1. 您跳过或不适当地应用了特征缩放 输入和输出。因此,数据可能难以处理 用于 TensorFlow。
    2. 使用不连续函数 ReLu 可能会引发问题。尝试使用其他激活函数,例如 tanh 或 sigmoid。

    【讨论】:

    • 非常感谢您的评论!将最后一层更改为 sigmoid 实际上确实修复了 NaN 丢失错误。现在,损失值最初看起来很正常(大约 3600),但很快又回落到 23 左右,这非常奇怪。您能否详细说明您关于特征缩放的第一点?谢谢!
    • 当然。想象一种情况,您在不同的尺度上设置了 2 个特征(例如,房价 x1:~1e6 美元,面积 x2:~10-100 m2)。如果不进行缩放,您的优化算法可能会在“最陡”(超)表面上来回反弹,甚至可能最终无法收敛(因此可能是 NaN)。对于给定的示例,您可以想象 (x1, x2) 表面具有如此陡峭的山谷。现在,如果你应用特征缩放 (xi
    • 哦,好吧,所以这是一种比较不同单位特征的方法。我不确定我是否理解你所说的“当不缩放时,你的优化函数会在最陡峭的超曲面上反弹并加强”的风险。为什么会来回反弹?我可能遗漏了什么
    • 与单位无关。假设你有两个特征,所以你的损失函数 J(x1, x2) 看起来像一个正常的表面:它有丘陵和山谷。如果您使用诸如梯度下降之类的优化器,它将尝试找出最陡峭的下降方式,并在那里迈出一步,以减少它(min J(x1, x2))。如果 x1 的数量级是百万,而 x2 的数量级是数百,会发生什么?然后 x1 与 x2 相比会发生很大变化,因此会产生尖锐的山谷。 -grad J 的每一步现在都可以“跳跃”穿过这样的山谷,并且可能不会落到底部(收敛问题,NaN...)。
    • 哦,好的。我现在明白了。因此,扩展我的功能将是防止这种情况发生的方法。非常感谢您的帮助!
    【解决方案2】:

    由于某些原因,您的训练过程出现了分歧,并且您的权重可能有无限值,这会导致 NaN 损失。原因可能很多,请尝试更改您的训练参数(使用较小的批次进行测试)。

    另外,对分类器中的最后一个输出使用 relu 不是常用方法,请尝试使用 sigmoid。

    【讨论】:

    • 非常感谢您的帮助!将最后一层更改为 sigmoid 实际上确实修复了 NaN 丢失错误。尽管如此,对于某些常数,所有预测的类仍然是 [0 0 0 0 0 0 0] 或 [5 5 5 5 5]。只是想知道,你怎么知道你的训练过程何时发生了分歧?我注意到我的损失值有时会上下波动
    【解决方案3】:

    据我了解,Relu 并未对神经网络的上限设置上限,因此它更有可能根据其实施情况去收敛。

    尝试将所有激活函数切换为 tanh 或 sigmoid。 Relu 一般用于 cnns 中的卷积。

    也很难确定您是否由于交叉熵而去收敛,因为我们不知道您是如何用您的 epsilon 值影响它的。尝试只使用残差,它更简单但仍然有效。

    5000-5000-4500 神经网络也是巨大的。您实际上不太可能需要这么大的网络。

    【讨论】:

    • 感谢您的评论!我将更改激活函数。至于神经元的数量,我有 5000 个,因为有大约 4500 个输出类。所以,根据我的信念,神经元的数量应该多于输出类的数量。还是我错过了什么?谢谢!
    • 很多人建议将隐藏层节点数设置在 numb_inputs 和 numb_outputs 之间。作为 MNIST 数据集上使用标准前馈模型的轶事点,我仅使用 8 个隐藏节点就能够获得 91% 的准确度。 (784 个输入,8 个隐藏节点,10 个输出),但直到我创建了一个包含大约 280 个隐藏节点的网络,我才能获得超过 97% 的准确度。我不相信所需的节点数量会线性扩展,因为您的连接数量呈指数增长。 IE numb_weights layer_n * layer_n+1.
    • 我认为 Alex Graves 有一篇研究论文?这表明增加神经元的数量有助于训练,但一旦收敛,你通常只需要最初训练的节点数量的一小部分。我现在不记得来源,但我会看看我是否可以挖掘它并在可能的时候链接它。如果您的准确性仍然太低,我会尝试使用小至 800 的网络并从那里开始增加节点。你的网络还没有收敛吗?
    • 非常感谢您的 cmets!现在正在收敛。损失值逐渐下降,但有时会随机下降 - 我认为这只是 NN 的一部分。我了解您的 cmets 关于节点数量的信息,这很有帮助!在这个问题中,我有大约 1000 个输入特征和 4500 个可能的输出类。我一直在尝试使用 2000 个具有 1 个和 2 个隐藏层的隐藏神经元、3000 个隐藏神经元和 5000 个隐藏神经元。它们似乎都没有我拥有的简单逻辑回归模型那么好。从理论上讲,MLP 应该更好吧?
    • 假设它是一个非线性函数,您正在解决的是。任意尖峰是正常的。你在训练集上做了多少次迭代?即使学习率设置为 0.3 高,它也必须进行 100 多次迭代。此外,如果学习率太低,可能需要很多次迭代才能收敛到一个合适的最小值。同样,如果您的学习率太高,可能会导致错误峰值(并可能增加去收敛的机会)
    猜你喜欢
    • 2017-02-04
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 2016-12-20
    • 1970-01-01
    • 2019-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多