TensorFlow имеет два способа оценить часть графика: Session.run
в списке переменных и Tensor.eval
. Есть ли разница между этими двумя?
В TensorFlow, в чем разница между Session.run() и Tensor.eval()?
Ответ 1
Если у вас есть Tensor
t, вызов t.eval()
эквивалентен вызову tf.get_default_session().run(t)
.
Вы можете сделать сеанс по умолчанию следующим образом:
t = tf.constant(42.0)
sess = tf.Session()
with sess.as_default(): # or `with sess:` to close on exit
assert sess is tf.get_default_session()
assert t.eval() == sess.run(t)
Самое важное отличие состоит в том, что вы можете использовать sess.run()
для извлечения значений многих тензоров на одном и том же шаге:
t = tf.constant(42.0)
u = tf.constant(37.0)
tu = tf.mul(t, u)
ut = tf.mul(u, t)
with sess.as_default():
tu.eval() # runs one step
ut.eval() # runs one step
sess.run([tu, ut]) # evaluates both tensors in a single step
Обратите внимание, что каждый вызов eval
и run
будет выполнять весь график с нуля. Чтобы кэшировать результат вычисления, назначьте его tf.Variable
.
Ответ 2
Сеанс часто задаваемых вопросов о тензорном потоке отвечает на тот же вопрос. Я бы просто пошел и оставил его здесь:
Если t
является объектом Tensor
, t.eval()
является сокращением для sess.run(t)
(где sess
- текущий сеанс по умолчанию. Два следующих фрагмента кода эквивалентны:
sess = tf.Session()
c = tf.constant(5.0)
print sess.run(c)
c = tf.constant(5.0)
with tf.Session():
print c.eval()
Во втором примере сеанс действует как диспетчер контекста, который приводит к его установке в качестве сеанса по умолчанию для времени жизни блока. Подход контекстного менеджера может привести к более сжатому коду для простых случаев использования (например, модульных тестов); если ваш код имеет дело с несколькими графиками и сеансами, может быть более прямым для явных вызовов Session.run()
.
Я бы порекомендовал вам, по крайней мере, пропустить все ответы на часто задаваемые вопросы, поскольку это может прояснить многое.
Ответ 3
eval()
не может обработать объект списка
tf.reset_default_graph()
a = tf.Variable(0.2, name="a")
b = tf.Variable(0.3, name="b")
z = tf.constant(0.0, name="z0")
for i in range(100):
z = a * tf.cos(z + i) + z * tf.sin(b - i)
grad = tf.gradients(z, [a, b])
init = tf.global_variables_initializer()
with tf.Session() as sess:
init.run()
print("z:", z.eval())
print("grad", grad.eval())
но Session.run()
может
print("grad", sess.run(grad))
поправь меня если я не прав
Ответ 4
В тензорном потоке вы создаете графики и передаете значения этому графику. Graph выполняет всю тяжелую работу и генерирует выходные данные на основе конфигурации, которую вы сделали в графике. Теперь, когда вы передаете значения в график, сначала вам нужно создать сеанс тензорного потока.
tf.Session()
После инициализации сеанса вы должны использовать этот сеанс, потому что все переменные и настройки теперь являются частью сеанса. Таким образом, существует два способа передачи внешних значений в граф, чтобы граф мог их принимать. Одним из них является вызов .run() во время использования выполняемого сеанса.
Другим способом, который по сути является ярлыком для этого, является использование .eval(). Я сказал ярлык, потому что полная форма .eval()
tf.get_default_session().run(values)
Вы можете проверить это сами. Вместо values.eval()
запустите tf.get_default_session().run(values)
. Вы должны получить такое же поведение.
eval использует сессию по умолчанию, а затем выполняет run().
Ответ 5
Самое главное помнить:
Единственный способ получить константу, переменную (любой результат) из TenorFlow - это сеанс.
Зная это, все остальное легко:
И
tf.Session.run()
иtf.Tensor.eval()
получают результаты из сеанса, гдеtf.Tensor.eval()
является ярлыком для вызоваtf.get_default_session().run(t)
Я также хотел бы описать метод tf.Operation.run()
как здесь:
После того, как граф был запущен в сеансе, Операция может быть выполнена, передав ее в
tf.Session.run()
.op.run()
является ярлыком для вызоваtf.get_default_session().run(op)
.