将外部优化器与张量流和随机网络元素一起使用
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 运行 次调用相同的一组号码。
我一直在使用 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 运行 次调用相同的一组号码。