使用tf.contrib.graph_editor克隆网络

use*_*103 5 tensorflow

我有这样的功能可以构建网络。

def build_network(inputs):
  # Some arbitrary set of variables and ops here. For example...
  out = tf.contrib.layers.fully_connected(inputs, 123)
  (...)
  return out
Run Code Online (Sandbox Code Playgroud)

然后,我用它来建立这样的网络。

inputs = tf.placeholder(...)
outputs = build_network(inputs)
Run Code Online (Sandbox Code Playgroud)

如果我想构建更多具有相同结构但有独立变量的网络,我只需要在其他变量范围以及可选的其他输入下再次调用build_network即可

我的问题是:如果此build_network不再可用,但原始网络的输入和输出可用,该怎么办?换句话说:如何将整个子图从输出一直克隆到另一个具有自己独立变量集但结构相同的变量作用域中的输入

我的理解是,一般来说tf.contrib.graph_editor尤其是graph_editor.copy正是我要做这些事情所需的工具。但是,我找不到使用它们的任何好例子。有什么建议么?

use*_*103 3

回应自己,我发现了一种看起来像是复制子图的方法。

from tensorflow.contrib import graph_editor as ge

# From the example above.
inputs = [tf.placeholder(...), ...]
outputs = build_network(inputs)

sgv = ge.make_view(ge.get_within_boundary_ops(
    tf.get_default_graph(),
    [t.op for t in outputs],
    [t.op for t in inputs]))

# This could be any new inputs. In this example I build new identical placeholders.
new_inputs = {p: tf.placeholder(dtype=p.dtype, shape=p.shape) for p in inputs}
new_sgv, info = ge.copy_with_input_replacements(sgv, new_inputs, dst_scope='copy')

new_inputs = [info.transformed(t) for t in inputs]
new_outputs = [info.transformed(t) for t in outputs]
Run Code Online (Sandbox Code Playgroud)

然而,现在我在尝试使用网络副本时遇到了一个新问题。副本中的新变量未初始化,尝试运行 tf.global_variables_initializer() 没有帮助。

原因是,由于这些变量的 tf.Variable 从未构建过,因此它们不是 GlobalKeys.GLOBAL_VARIABLES 集合的一部分。我可以轻松找到与这些变量相对应的操作以及它们在原始和副本之间的映射,但我无法从中构建 tf.Variable 。

我发现了一些棘手的解决方法来进行初始化,但它仅适用于集合中的变量。

init_ops = []
for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES):
  if v.op in sgv.ops:
    init_ops.append(info.transformed(v.initializer))

...

session.run([tf.global_variables_initializer()] + init_ops)
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来做到这一点?理想情况下,允许为复制的变量创建 tf.Variables 以将它们添加到全局变量集合中。或者,如果这是不可能的,至少有一种可靠的方法来获取初始化操作,而不必找到原始网络的 tf.Variable 对象。