我试图了解在上述情况下with
块的行为。我假设总是只有一张图和一个会话。我了解我有(至少?)在with
块中使用会话的两种工作方式:
示例1 :使用创建上下文管理器的as_default()
:
Same documentation说:
与
with
关键字一起使用以指定对tf.Operation.run
或tf.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源代码超出了我的知识。有人可以解释吗?
答案 0 :(得分:1)
它们做的事情略有不同,因此根据用法,每个可能正确,也可能不正确。 tf.Session.as_default()
只会确保将会话设置为默认会话,因此对eval
和run
的调用将默认使用该会话:
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()
而不是依赖于默认会话,但这主要取决于我的个人品味。