【问题标题】:Sharing variables between threads in Tensorflow在 Tensorflow 中的线程之间共享变量
【发布时间】:2016-03-16 12:54:15
【问题描述】:

我正在尝试使用 Python 线程通过 TensorFlow 实现异步梯度下降。在主代码中,我定义了图形,包括一个训练操作,它获取一个变量来保持global_step 的计数:

with tf.variable_scope("scope_global_step") as scope_global_step:
    global_step = tf.get_variable('global_step', [], initializer=tf.constant_initializer(0), trainable=False)
optimizer = tf.train.GradientDescentOptimizer(FLAGS.learning_rate)
train_op = optimizer.minimize(loss, global_step=global_step)

如果我打印global_step 的名字,我会得到:

scope_global_step/global_step:0

主代码还启动了几个线程来执行training方法:

threads = [threading.Thread(target=training, args=(sess, train_op, loss, scope_global_step)) for i in xrange(NUM_TRAINING_THREADS)]
for t in threads: t.start()

如果global_step 的值大于或等于FLAGS.max_steps,我希望每个线程停止执行。为此,我构建了training 方法,如下所示:

def training(sess, train_op, loss, scope_global_step):
    while (True):
         _, loss_value = sess.run([train_op, loss])
         with tf.variable_scope(scope_global_step, reuse=True): 
            global_step = tf.get_variable('global_step', [], initializer=tf.constant_initializer(0), trainable=False)
            global_step = global_step.eval(session=sess)
            if global_step >= FLAGS.max_steps: break

失败并显示以下消息:

ValueError:共享不足:变量 scope_global_step/global_step 不存在,不允许。您的意思是在 VarScope 中设置 reuse=None 吗?

我可以看到 :0 在第一次创建时添加到变量的名称中,当我尝试检索它时,没有使用该后缀。为什么是这样? 如果我在尝试检索变量时手动将后缀添加到变量的名称中,它仍然声称该变量不存在。为什么 TensorFlow 找不到变量?变量不应该在线程之间自动共享吗?我的意思是,所有线程都在同一个会话中运行,对吗?

还有一个与我的training 方法相关的问题:global_step.eval(session=sess) 会再次执行图表,还是会在执行train_oploss 操作后获取分配给gloabl_step 的值?一般来说,从要在 Python 代码中使用的变量中获取值的推荐方法是什么?

【问题讨论】:

    标签: python multithreading tensorflow


    【解决方案1】:

    TL;DR: 将您在第一个代码片段中创建的 global_step tf.Variable 对象作为训练线程参数之一传递,并在传入的变量上调用 sess.run(global_step) .

    作为一般规则,您的训练循环(尤其是单独线程中的训练循环)不应修改图表。 tf.variable_scope() 上下文管理器和tf.get_variable() 可以 修改图形(尽管它们并不总是),所以你不应该在训练循环中使用它们。最安全的做法是在创建训练线程时将global_step 对象(您首先创建的)作为args 元组之一传递。然后你可以简单地将你的训练函数重写为:

    def training(sess, train_op, loss, global_step):
        while (True):
             _, loss_value = sess.run([train_op, loss])
             current_step = sess.run(global_step)
             if current_step >= FLAGS.max_steps: break
    

    要回答您的其他问题,运行global_step.eval(session=sess)sess.run(global_step) 只会获取global_step 变量的当前值,并且不会重新执行图表的其余部分。这是获取 tf.Variable 值以在 Python 代码中使用的推荐方法。

    【讨论】:

    • 谢谢@mrry。您的解决方案肯定更清洁。但是,我仍然想知道为什么 tf.get_variable() 找不到该变量。你能解释一下为什么会这样吗?谢谢!
    • 我认为这实际上失败了,因为在不同的线程中运行tf.variable_scope() 实际上是指与您最初创建变量的实例不同的tf.Graph 实例。如果您执行with sess.graph.as_default(), tf.variable_scope("scope_global_step", reuse=True): 之类的操作,它会这样做,但仅当您有一个训练线程时。该图对于写入不是线程安全的,并且输入变量范围会导致一些图内部数据结构被更新,因此您永远不应该这样做:)。
    • 再次感谢@mrry。我想我学到了一两件重要的东西:-)
    猜你喜欢
    • 2017-07-22
    • 2023-04-05
    • 1970-01-01
    • 2021-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-01
    相关资源
    最近更新 更多