将外部优化器与张量流和随机网络元素一起使用

Using external optimizers with tensorflow and stochastic network elements

我一直在使用 Tensorflow 和 openopt 的 l-bfgs 优化器。设置回调以允许 Tensorflow 计算 l-bfgs 的梯度和损失评估非常容易,但是,我在弄清楚如何将随机元素(如 dropout)引入训练过程时遇到了一些问题。

在线搜索时,l-bfgs对损失函数进行多次评估,需要与之前的梯度评估在同一个网络上运行。但是,似乎对于 tf.nn.dropout 函数的每次评估,都会创建一组新的 dropouts。我正在寻找一种方法来修复损失函数的多次评估中的丢失,然后允许它在 l-bfgs 的梯度步骤之间改变。我假设这与 tensorflow 中的控制流操作有关,但实际上并没有关于如何使用它们的好教程,它们对我来说有点神秘。

感谢您的帮助!

Drop-out 依赖于使用 random_uniform,这是一个有状态的操作,我没有找到重置它的方法。但是,您可以通过替换您自己的随机数并将它们提供给与 random_uniform 相同的输入点来破解它,替换生成的值

采取以下代码:

tf.reset_default_graph()
a = tf.constant([1, 1, 1, 1, 1], dtype=tf.float32)
graph_level_seed = 1
operation_level_seed = 1
tf.set_random_seed(graph_level_seed)
b = tf.nn.dropout(a, 0.5, seed=operation_level_seed)

可视化图形以查看 random_uniform 连接的位置

您可以看到 dropout 通过名称为 mydropout/random_uniform/(random_uniform)Add 操作获取 random_uniform 的输入。实际上 /(random_uniform) 后缀是出于 UI 的原因,真正的名字是 mydropout/random_uniform 正如你可以通过打印 tf.get_default_graph().as_graph_def() 看到的那样。这给了你缩短的张量名称。现在您附加 :0 以获得实际的张量名称。 (旁注:操作可能会产生多个张量,这些张量对应于后缀 :0:1 等。由于只有一个输出是最常见的情况,因此 :0 隐含在 GraphDef 和 node 输入等同于 node:0。然而,当使用 feed_dict 时,:0 不是隐含的,所以你必须明确地写 node:0)

现在您可以通过生成您自己的随机数(与传入张量具有相同形状)并在调用之间重复使用它们来修复种子。

tf.reset_default_graph()
a = tf.constant([1, 1, 1, 1, 1], dtype=tf.float32)
graph_level_seed = 1
operation_level_seed = 1
tf.set_random_seed(graph_level_seed)
b = tf.nn.dropout(a, 0.5, seed=operation_level_seed, name="mydropout")
random_numbers = np.random.random(a.get_shape()).astype(dtype=np.float32)
sess = tf.Session()
print sess.run(b, feed_dict={"mydropout/random_uniform:0":random_numbers})
print sess.run(b, feed_dict={"mydropout/random_uniform:0":random_numbers})

您应该会看到与 2 运行 次调用相同的一组号码。