【问题标题】:Determinism in tensorflow gradient updates?张量流梯度更新中的确定性?
【发布时间】:2017-02-17 16:42:54
【问题描述】:

所以我有一个用 Tensorflow 编写的非常简单的 NN 脚本,我很难追踪一些“随机性”的来源。

我已经录了

  • 权重,
  • 渐变,
  • 逻辑

在我训练时我的网络,对于第一次迭代,很明显一切都以相同的方式开始。我有一个用于读取数据的 SEED 值,以及一个用于初始化网络权重的 SEED 值。那些我永远不会改变的。

我的问题是,在每次重新运行的第二次迭代中,我开始看到 gradients 发散(少量,例如 1e-6 左右) .然而,随着时间的推移,这当然会导致不可重复的行为。

这可能是什么原因?我不知道任何可能的随机性来源可能来自哪里......

谢谢

【问题讨论】:

  • 你使用 GPU 吗? GPU 上的各种操作由于使用 CUDA 原子(如 tf.reduce_sum)而具有不确定性
  • 还有一些 SSE 优化会导致不确定的结果,您可以尝试编译没有任何优化的 TensorFlow,看看是否是这种情况(详情 -- blog.nag.com/2011/02/wandering-precision.html
  • 嗨 @YaroslavBulatov 是的,我确实在使用 GPU。
  • @YaroslavBulatov 对优化很感兴趣……还有关于 GPU 部分。这是否意味着无论是 CPU 还是 GPU,我们总能期望得到这种行为?那么,我们如何才能真正在 TF 中获得确定性结果?...
  • 我也有类似的问题,请参阅:stackoverflow.com/questions/42412660/…

标签: random floating-point tensorflow precision random-seed


【解决方案1】:

如果您在 CPU (export CUDA_VISIBLE_DEVICES=) 上运行网络,在 Eigen 线程池 (tf.Session(config=tf.ConfigProto(intra_op_parallelism_threads=1)) 中使用单线程,一个 Python 线程(没有多线程队列运行器),则很有可能获得确定性结果您可以从 tf.batch) 之类的操作中获得,以及一个明确定义的操作顺序。在某些情况下,也使用inter_op_parallelism_threads=1 可能会有所帮助。

一个问题是浮点加法/乘法是非关联的,因此获得确定性结果的一种万​​无一失的方法是使用整数算术或量化值。

除此之外,您可以隔离哪个操作是不确定的,并尽量避免使用该操作。例如,有tf.add_n op,它没有说明它对值求和的顺序,但不同的顺序会产生不同的结果。

获得确定性结果是一场艰苦的战斗,因为确定性与性能相冲突,而性能通常是更受关注的目标。尝试在重新运行时获得完全相同的数字的另一种方法是关注数值稳定性——如果你的算法是稳定的,那么即使确切的参数值可能略有不同,你也会得到可重现的结果(即相同数量的错误分类)

【讨论】:

  • (1/2) 谢谢雅罗斯拉夫,有几件事:1) 但是有没有一种简单的方法可以强制 TF 只使用 CPU? (我想可能会扩展(export CUDA_VISIBLE_DEVICES=))?我应该在命令行中逐字输入吗? 2)关于整数/浮点值 - 你是说我可以做的一个实验是将我的所有参数(和相关值)更改为 tf.int16 例如,而不是现在的 tf.float32 ,尝试并获得可重复性,因为整数运算不会遇到您强调的相同浮点问题?
  • (2/2) 关于可重复性,是的,我想尝试解决这个问题,因为我试图深入了解一个错误。基本上,随着我的训练进行,我的(数据)损失会爆发到非常高的值(有时甚至是 NaN)。然而,这似乎只在(数据)损失开始时达到极低值时才会发生。有时网络会恢复,但有时不会,所以这实际上是主要问题。 :-/ 奇怪的是我使用了所有的 TF 函数,而且图表甚至是 (tensorflow.org/versions/r0.11/tutorials/deep_cnn/index.html) 的骨架化版本。
  • “损失爆炸”是一种普遍现象,是随机梯度下降的一个特性。常见的解决方案是降低学习率和/或添加正则化。
  • 奇怪的是,这种“爆炸性损失”似乎发生在(数据)损失本身真的接近 0 时,(softmax 损失 btw),而当损失不是。你是这个意思吗?最后,关于为什么会出现这种现象,你有什么好的论文可以推荐吗?谢谢雅罗斯拉夫!
  • 也许某个地方的分母会变为零? IE,如果你在做逻辑回归,并且你的数据变得完美分类,你会爆炸到无穷大。在参数上添加 L2 正则化可以解决这个问题
【解决方案2】:

tensorflow reduce_sum 运算是特别已知的非确定性的。此外,reduce_sum 用于计算偏差梯度。

This post 讨论了一种避免使用 reduce_sum 的解决方法(即,将任何向量的点积与全 1 的向量相乘与 reduce_sum 相同)

【讨论】:

    【解决方案3】:

    我也遇到过同样的问题。。 对我来说可行的解决方案是:

    1- 使用tf.set_random_seed(1) 以使所有 tf​​ 函数在每次新运行时都具有相同的种子

    2- 使用 CPU 而不是 GPU 训练模型,以避免由于精度导致 GPU 非确定性操作。

    【讨论】:

      猜你喜欢
      • 2016-08-20
      • 1970-01-01
      • 2023-03-27
      • 2017-11-04
      • 1970-01-01
      • 1970-01-01
      • 2016-09-12
      • 2018-03-28
      相关资源
      最近更新 更多