使用Context Manager与会话进行Tensorflow

时间:2018-10-09 20:49:32

标签: python tensorflow

我试图了解在上述情况下with块的行为。我假设总是只有一张图和一个会话。我了解我有(至少?)在with块中使用会话的两种工作方式:

示例1 :使用创建上下文管理器的as_default()
Same documentation说:

  

with关键字一起使用以指定对   tf.Operation.runtf.Tensor.eval应在此执行   会议。

# Create session
sess = tf.Session()
# Enter with block on a new context manager
with sess.as_default():
  # Train: Following line should result calling tf.Operation.run
  sess.run([optimizer, loss], feed_dict={x: x_train, y: y_train)
  # Eval: Following line should result calling tf.Tensor.eval
  sess.run([loss], feed_dict={x: x_eval, y: y_eval)

示例2:,如same documentation in a lower section所述,会话被阻止:

  

或者,您可以使用with tf.Session():创建一个会话   在退出上下文时会自动关闭,包括   引发未捕获的异常。

# Enter with block on session instead of Context Manager
with tf.Session() as sess:
  # Train: Following line seems calling tf.Operation.run as per my test
  sess.run([optimizer, loss], feed_dict={x: x_train, y: y_train)
  # Eval: Following is unclear
  sess.run([loss], feed_dict={x: x_eval, y: y_eval)

我想了解什么是正确的用法,因为我看到了这两种情况的GitHub示例,但是当然没有结果。在我的测试中,示例1和2均适用于训练。对于评估,似乎存在我无法理解的差异。浏览Tensorflow源代码超出了我的知识。有人可以解释吗?

1 个答案:

答案 0 :(得分:1)

它们做的事情略有不同,因此根据用法,每个可能正确,也可能不正确。 tf.Session.as_default()只会确保将会话设置为默认会话,因此对evalrun的调用将默认使用该会话:

import tensorflow as tf

sess = tf.Session()
with sess.as_default():
    print(sess is tf.get_default_session())  # True

但是,如文档中所述,tf.Session.as_default()with块之后将自动关闭会话。如果需要,可以将会话本身用作上下文管理器:

import tensorflow as tf

with tf.Session() as sess:
    # Do something with the session
sess.run([])  # RuntimeError: Attempted to use a closed Session.

但是,尽管(从我的角度来看)虽然没有明确记录,但是使用会话作为上下文管理器 也将其设置为默认会话。

import tensorflow as tf

with tf.Session() as sess:
    print(sess is tf.get_default_session())  # True

那么tf.Session.as_default()的意义是什么?好吧,简单来说,当您想暂时将一个会话设为默认会话,但又不想在此之后将其关闭时(在这种情况下,您应该稍后手动将其关闭,或者将其用作外部上下文管理器)。当您有多个打开的会话时,这可能是最相关的。考虑以下情况:

import tensorflow as tf

with tf.Session() as sess1, tf.Session() as sess2:
    print(sess2 is tf.get_default_session())  # True

此处sess2是默认设置,因为稍后添加了它的上下文(可以认为它是sess1创建的上下文的“内部”)。但是现在也许您想暂时将sess1设置为默认值。但是,您不能再将sess1本身用作上下文管理器:

import tensorflow as tf

with tf.Session() as sess1, tf.Session() as sess2:
    # Do something with sess2
    with sess1:
        # RuntimeError: Session context managers are not re-entrant.
        #               Use `Session.as_default()` if you want to enter
        #               a session multiple times.

因此,您可以使用tf.Session.as_default()在一个默认会话和另一个默认会话之间切换:

import tensorflow as tf

with tf.Session() as sess1, tf.Session() as sess2:
    with sess1.as_default():
        # Do something with sess1
    with sess2.as_default():
        # Do something with sess2
        # This is not really needed because sess2 was the default
        # in the outer context but you can add it to be explicit
# Both sessions are closed at the end of the outer context

当然,如果需要的话,即使只有一个会话,您也可以更加明确:

import tensorflow as tf

with tf.Session() as sess, sess.as_default():
    # ...

就我个人而言,我从未在实际代码中使用过tf.Session.as_default(),但是我再次很少需要使用多个会话,因此我更喜欢使用tf.Session.run()而不是依赖于默认会话,但这主要取决于我的个人品味。