В 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).