【问题标题】:Run train op multiple times in tensorflow在张量流中多次运行训练操作
【发布时间】:2016-10-05 07:50:26
【问题描述】:

我有一些相当大的批量大小,我想对其进行多个渐变步骤。虽然我可以使用 python for 循环轻松地做到这一点,但我想可能有一种更有效的方法,它不涉及在每次迭代时将数据传输到 gpu。我曾多次尝试将 train op 放入 fetch 列表中,但我不确定它实际上是否多次运行(运行时完全相同)。

【问题讨论】:

    标签: tensorflow


    【解决方案1】:

    如果您执行sess.run([myop,myop]),则只会运行一次myop

    如果您想运行操作,但不将其结果获取到 Python 运行时,您可以使用控制依赖项。一个简单的方法是使用group op,即

    sess.run(tf.group(myop))
    sess.run(tf.group(myop))
    

    如果您的图表很大,您可能会通过在运行调用之间构建 group op 来获得额外的开销(对于 >10k 节点图表可能需要 10-100 毫秒),因此您可以提前构建它

    myop_nooutput = tf.group(myop)
    sess.run(myop_nooutput)
    sess.run(myop_nooutput)
    

    【讨论】:

    • 您的示例中的提要字典在哪里?
    • 您可以将 feed_dict 作为额外参数传递给 sess.run
    • 所以 feed_dict 会在每次运行时单独传递? (这是我希望避免的)。
    • 您可以通过首先将数据放到 GPU 上来避免多次 feed_dict 传输,就像这里的答案 stackoverflow.com/questions/37596333/…
    • 您可以使用变量和来自占位符的assign 将“feed_dict”的内容保存到 GPU 上的变量中,然后运行 ​​sess.run 几次,其中相关操作从变量而不是占位符
    【解决方案2】:

    如果您有可变大小的批处理,那么变量不适合保存它,您可以使用持久张量在 run 调用之间保留此数据。这是一个玩具示例

    t = tf.int32
    params = tf.Variable(tf.ones_initializer((), dtype=dt))
    data_batches = [[1], [2, 3], [4, 5, 6]]
    
    # op that uploads data to TF and saves it as a persistent Tensor
    data_saver_placeholder = tf.placeholder(dt)
    tensor_handle_op = tf.get_session_handle(data_saver_placeholder)
    
    data_placeholder, data = tf.get_session_tensor(dt)
    train_op = tf.assign_add(params, tf.reduce_prod(data)) 
    init_op = tf.initialize_all_variables()
    sess = tf.Session()
    sess.run(init_op)
    
    for batch in data_batches:
        # upload tensor to TF runtime and save its handle
        tensor_handle = sess.run(tensor_handle_op, feed_dict={data_saver_placeholder: batch})
        # run train op several times reusing same data
        for i in range(3):
            sess.run(train_op, feed_dict={data_placeholder: tensor_handle.handle})
    
    
    assert sess.run(params) == 382
    

    【讨论】:

    • 我使用这个解决方案有一段时间了,但由于 get_session_tensor API 的变化,它不再有效 - 除了 dtype 之外,现在还需要一个句柄。
    • 如果看源码,handle 仅用于确定张量的设备。因此,如果您使用 CPU,您可以在 CPU 上创建一个虚拟句柄并重用它
    • 谢谢,雅罗斯拉夫,但我对两件事感到困惑。首先,虚拟句柄不应该在 GPU 而不是 CPU 上,因为目的是避免大量从 CPU 到 GPU 的多次传输?其次,为什么我们不需要调用delete_session_tensor来释放内存?
    • 你的例子中的 dt 是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-15
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多