【问题标题】:Run multiple pre-trained Tensorflow nets at the same time同时运行多个预训练的 Tensorflow 网络
【发布时间】:2016-08-26 23:31:30
【问题描述】:

我想做的是同时运行多个预训练的 Tensorflow 网络。因为每个网络内部的一些变量的名称可以相同,所以常见的解决方案是在创建网络时使用名称范围。但是,问题是我已经训练了这些模型并将训练后的变量保存在几个检查点文件中。在创建网络时使用名称范围后,我无法从检查点文件加载变量。

例如,我训练了一个 AlexNet,我想比较两组变量,一组来自 epoch 10(保存在文件 epoch_10.ckpt),另一组来自 epoch 50(保存在文件 epoch_50.ckpt)。因为这两个是完全一样的net,所以里面的变量名是一样的。我可以使用创建两个网络

with tf.name_scope("net1"):
    net1 = CreateAlexNet()
with tf.name_scope("net2"):
    net2 = CreateAlexNet()

但是,我无法从 .ckpt 文件加载经过训练的变量,因为当我训练这个网络时,我没有使用名称范围。尽管我可以在训练网络时将名称范围设置为“net1”,但这会阻止我加载 net2 的变量。

我试过了:

with tf.name_scope("net1"):
    mySaver.restore(sess, 'epoch_10.ckpt')
with tf.name_scope("net2"):
    mySaver.restore(sess, 'epoch_50.ckpt')

这不起作用。

解决这个问题的最佳方法是什么?

【问题讨论】:

    标签: python tensorflow


    【解决方案1】:

    最简单的解决方案是为每个模型创建使用单独图表的不同会话:

    # Build a graph containing `net1`.
    with tf.Graph().as_default() as net1_graph:
      net1 = CreateAlexNet()
      saver1 = tf.train.Saver(...)
    sess1 = tf.Session(graph=net1_graph)
    saver1.restore(sess1, 'epoch_10.ckpt')
    
    # Build a separate graph containing `net2`.
    with tf.Graph().as_default() as net2_graph:
      net2 = CreateAlexNet()
      saver2 = tf.train.Saver(...)
    sess2 = tf.Session(graph=net1_graph)
    saver2.restore(sess2, 'epoch_50.ckpt')
    

    如果由于某种原因这不起作用,并且您必须使用单个 tf.Session(例如,因为您想在另一个 TensorFlow 计算中组合来自两个网络的结果),最好的解决方案是:

    1. 按照您已经在做的那样在名称范围内创建不同的网络,并且
    2. 为两个网络创建单独的tf.train.Saver 实例,并使用附加参数重新映射变量名称。

    constructing 保存器时,您可以将字典作为var_list 参数传递,将检查点中的变量名称(即没有名称范围前缀)映射到您在其中创建的tf.Variable 对象每个模型。

    您可以通过编程方式构建var_list,并且应该能够执行以下操作:

    with tf.name_scope("net1"):
      net1 = CreateAlexNet()
    with tf.name_scope("net2"):
      net2 = CreateAlexNet()
    
    # Strip off the "net1/" prefix to get the names of the variables in the checkpoint.
    net1_varlist = {v.name.lstrip("net1/"): v
                    for v in tf.get_collection(tf.GraphKeys.VARIABLES, scope="net1/")}
    net1_saver = tf.train.Saver(var_list=net1_varlist)
    
    # Strip off the "net2/" prefix to get the names of the variables in the checkpoint.
    net2_varlist = {v.name.lstrip("net2/"): v
                    for v in tf.get_collection(tf.GraphKeys.VARIABLES, scope="net2/")}
    net2_saver = tf.train.Saver(var_list=net2_varlist)
    
    # ...
    net1_saver.restore(sess, "epoch_10.ckpt")
    net2_saver.restore(sess, "epoch_50.ckpt")
    

    【讨论】:

    • 使用 lstrip 剥离前缀可能会导致不正确的结果。请改用切片。代码的其他部分完美运行。另一个问题是我发现一个变量的名称有一个像“:0”,“:1”这样的后缀。在将变量存储到检查点文件之前,是否需要去掉这个后缀?
    • 有人试过这个答案吗?我遇到了 restore 函数没有做任何事情的问题:stackoverflow.com/questions/41607144/…
    • 这实际上应该是v.op.name 而不是v.name,如documentation for Saver 中所述。
    【解决方案2】:

    我也有同样困扰我很久的问题。我在这里找到了一个很好的解决方案:Loading two models from Saver in the same Tensorflow sessionTensorFlow checkpoint save and read

    tf.train.Saver() 的默认行为是将每个变量与相应操作的名称相关联。这意味着每次构造tf.train.Saver() 时,它都会包含之前调用的所有变量。因此,您应该创建不同的图表并使用它们运行不同的会话。

    【讨论】:

      猜你喜欢
      • 2017-05-23
      • 2016-03-31
      • 1970-01-01
      • 2016-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-05
      • 1970-01-01
      相关资源
      最近更新 更多