Работа с несколькими графиками в TensorFlow

Может кто-нибудь объяснить мне, как name_scope работает в TensorFlow?

Предположим, что у меня есть следующий код:

import tensorflow as tf

g1 = tf.Graph()
with g1.as_default() as g:
    with g.name_scope( "g1" ) as scope:
        matrix1 = tf.constant([[3., 3.]])
        matrix2 = tf.constant([[2.],[2.]])
        product = tf.matmul(matrix1, matrix2)

tf.reset_default_graph()

g2 = tf.Graph()
with g2.as_default() as g:
    with g.name_scope( "g2" ) as scope:
        matrix1 = tf.constant([[4., 4.]])
        matrix2 = tf.constant([[5.],[5.]])
        product = tf.matmul(matrix1, matrix2)

tf.reset_default_graph()

with tf.Session( graph = g1 ) as sess:
    result = sess.run( product )
    print( result )

Когда я запускаю этот код, я получаю следующее сообщение об ошибке:

Tensor Tensor("g2/MatMul:0", shape=(1, 1), dtype=float32) is not an element of this graph.

Согласен: "g2/MatMul" не является элементом графика g1, но почему он выбирает "g2/MatMul", когда график сеанса установлен на g1? Почему он не выбирает "g1/MatMul"?


Изменить

Кажется, что работает следующий код:

import tensorflow as tf

g1 = tf.Graph()
with g1.as_default() as g:
    with g.name_scope( "g1" ) as g1_scope:
        matrix1 = tf.constant([[3., 3.]])
        matrix2 = tf.constant([[2.],[2.]])
        product = tf.matmul( matrix1, matrix2, name = "product")

tf.reset_default_graph()

g2 = tf.Graph()
with g2.as_default() as g:
    with g.name_scope( "g2" ) as g2_scope:
        matrix1 = tf.constant([[4., 4.]])
        matrix2 = tf.constant([[5.],[5.]])
        product = tf.matmul( matrix1, matrix2, name = "product" )

tf.reset_default_graph()

use_g1 = False

if ( use_g1 ):
    g = g1
    scope = g1_scope
else:
    g = g2
    scope = g2_scope

with tf.Session( graph = g ) as sess:
    tf.initialize_all_variables()
    result = sess.run( sess.graph.get_tensor_by_name( scope + "product:0" ) )
    print( result )

Перевернув переключатель use_g1, в сеансе будет отображаться график g1 или g2. Является ли это тем, как должна была работать область определения имен?

Ответы

Ответ 1

Ваша product - глобальная переменная, и вы указали ее на "g2/MatMul".

В частности,

Try

print product

и вы увидите

Tensor("g2/MatMul:0", shape=(1, 1), dtype=float32)

Итак, система берет "g2/MatMul:0", так как это имя Тензора, и пытается найти его в графе g1, так как этот график вы устанавливаете для сеанса. Кстати, вы можете увидеть все узлы в графе print [n.name for n in g1.as_graph_def().node]

Как правило, использование более одного графика редко бывает полезным. Вы не можете объединить их и не можете пропускать между ними тензоры. Я бы рекомендовал просто делать

tf.reset_default_graph()
a = tf.Constant(2)
sess = tf.InteractiveSession()
....

Таким образом, у вас будет один график по умолчанию и один сеанс по умолчанию, и вы можете в большинстве случаев не указывать график или сеанс. Если вам когда-либо понадобится обращаться к ним явно, вы можете получить их от tf.get_default_graph() или tf.get_default_session()

Ответ 2

Это довольно некро, но он все еще является лучшим результатом поиска для вопросов, связанных с этим, и я думал, что это может помочь сделать очень явным то, что предыдущие ответы (которые правильны) отмечают попутно:

Переменная Q product является переменной python. Таким образом, он указывает на объект: если он определен, он указывает на вывод tf.Tensor matmul tf.Operation, определенный в name_scope 'g1'. Позднее переопределяется указание на другой объект, вывод tf.Tensor "g2". Эта переменная python никогда не слышала о tf.name_scope и не заботится.

Вот почему вам нужно выполнять поиск с помощью атрибутов name объектов tensorflow... Те, с помощью name_scopes, являются уникальными и доступными. Или создайте отдельные переменные python - уникальные и доступные в соответствии с правилами проверки python - укажите на каждый объект tf.Tensor, который вы хотите ссылаться.

Не знаю, если это полезно для кого-то другого, но если я когда-нибудь забуду, я буду благодарен за свое прошлое за это.

Ответ 3

У меня были аналогичные трудности, связанные с несколькими графиками на ноутбуке IPython. То, что работает для моих целей, заключается в инкапсуляции каждого графика и его сеанса в функцию. Я понимаю, что это скорее хак, я думаю, я ничего не знаю об пространствах имен, и я знаю, что OP хочет чего-то в этом направлении. Возможно, это поможет кому-то, я не знаю, вы также можете передавать результаты между вычислениями.

import tensorflow as tf

def Graph1():
    g1 = tf.Graph()
    with g1.as_default() as g:
        matrix1 = tf.constant([[3., 3.]])
        matrix2 = tf.constant([[2.],[2.]])
        product = tf.matmul( matrix1, matrix2, name = "product")

    with tf.Session( graph = g ) as sess:
        tf.initialize_all_variables().run()
        return product


def Graph2(incoming):
    i = incoming
    g2 = tf.Graph()
    with g2.as_default() as g:
        matrix1 = tf.constant([[4., 4.]])
        matrix2 = tf.constant([[5.],[5.]])
        product = tf.matmul( matrix1, matrix2, name = "product" )

    with tf.Session( graph = g ) as sess:
        tf.initialize_all_variables().run()
        print product
        print i

print Graph1()

Graph2(Graph1())

Ответ 4

Ваша проблема в том, что вы вызываете последнюю переменную product, которая указывает на тензор, созданный на g2 - вы перезаписали его во второй области. Просто перепишите все свои переменные, и вам должно быть хорошо идти. Рабочий код ниже.

import tensorflow as tf

g1 = tf.Graph() with g1.as_default() as g:
    with g.name_scope( "g1" ) as scope:
        matrix11 = tf.constant([[3., 3.]])
        matrix21 = tf.constant([[2.],[2.]])
        product1 = tf.matmul(matrix11, matrix21)

tf.reset_default_graph()

g2 = tf.Graph() with g2.as_default() as g:
    with g.name_scope( "g2" ) as scope:
        matrix12 = tf.constant([[4., 4.]])
        matrix22 = tf.constant([[5.],[5.]])
        product2 = tf.matmul(matrix12, matrix22)

tf.reset_default_graph()

with tf.Session( graph = g1 ) as sess:
    result = sess.run( product1 )
    print( result )

Ответ 5

У вас есть 3 графика, а не 2 графика (g1 или g2).

Вы можете видеть 3 графика по id()

...

print 'g1           ', id(g1)
print 'g2           ', id(g2)
print 'current graph', id ( tf.get_default_graph() )

with tf.Session( graph = g1 ) as sess:
    result = sess.run( product )
    print( result )

Использование "с g1.as_default():" сделать ту же ошибку

...

with g1.as_default() :
    with tf.Session( graph = g1 ) as sess:
        result = sess.run( product )
        print( result )

Потому что у вас есть два "продукта", а не один.

g1 = tf.Graph()
with g1.as_default() as g:
    ...
    print 'g1 product', id ( product )

...

g2 = tf.Graph()
with g2.as_default() as g:
    ...
    print 'g2 product', id ( product )

with tf.Session( graph = g1 ) as sess:
    print 'last product', id(product)
    ...

последний продукт == g2 product

...
    product = tf.matmul(matrix1, matrix2, name='g1_product')
...
with g1.as_default() as g:
    with tf.Session() as sess:
        product = g.get_tensor_by_name(  "g1_product:0" )
        result = sess.run( product )
        print( result )

Работа над кодом.

Но две переменные с одним и тем же именем (произведение)

Инкапсуляция с классом хороша?

Ответ 6

Я написал два фрагмента, чтобы делать то, что вы пытаетесь сделать.

Первые переключатели между графиками и НЕ используют name_scope. Второй использует default_graph для обоих опций и использует name_scope для переключения между ними...

import tensorflow as tf

g1 = tf.Graph()
with g1.as_default() as g:
  matrix1 = tf.constant([[3., 3.]])
  matrix2 = tf.constant([[2.],[2.]])
  tf.matmul(matrix1, matrix2, name="productX")

g2 = tf.Graph()
with g2.as_default() as g:
  matrix1 = tf.constant([[4., 4.]])
  matrix2 = tf.constant([[5.],[5.]])
  tf.matmul(matrix1, matrix2, name="productX")

product_op = g1.get_tensor_by_name(  "productX:0" )
with tf.Session( graph = g1 ) as sess:
    result = sess.run( product_op )
    print( result )

product_op = g2.get_tensor_by_name(  "productX:0" )
with tf.Session( graph = g2 ) as sess:
  result = sess.run( product_op )
  print( result )

ПРИМЕЧАНИЕ A) Я выбрал сброс графика по умолчанию (график по умолчанию никогда не используется), а B) я избавился от переменной "product" и дал операции имя, вместо этого

Важным кодом переключения является...

product_op = g2.get_tensor_by_name(  "productX:0" )

где мы используем имя переменной из двух графиков для различения двух опций продукта.

Обратите внимание на раздражающее ": 0", которое вы должны поставить в конце имени переменной.

И теперь с помощью name_scope...

import tensorflow as tf

g = tf.get_default_graph()

matrix1 = tf.constant([[3., 3.]])
matrix2 = tf.constant([[2.],[2.]])
with g.name_scope("prodA"):
  tf.matmul(matrix1, matrix2, name="productX")

matrix1 = tf.constant([[4., 4.]])
matrix2 = tf.constant([[5.],[5.]])
with g.name_scope("prodB"):
  tf.matmul(matrix1, matrix2, name="productX")

with tf.Session() as sess:

  product_op = g.get_tensor_by_name(  "prodA/productX:0" )
  result = sess.run( product_op )
  print( result )

  product_op = g.get_tensor_by_name(  "prodB/productX:0" )
  result = sess.run( product_op )
  print( result )

Теперь строка переключения кода - это...

product_op = g.get_tensor_by_name(  "prodB/productX:0" )

ПРИМЕЧАНИЕ.) Нет переключения между графиками или сеансами. B) name_scope дает вам вид иерархии иерархии структуры каталогов.

Каковы плюсы и минусы переключения графика и имен? Если бы кто-то написал блог, я бы это прочитал!

Я не думаю, что переключение между графиками и сеансами может быть очень быстрым.