Работа с несколькими графиками в 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 дает вам вид иерархии иерархии структуры каталогов.
Каковы плюсы и минусы переключения графика и имен? Если бы кто-то написал блог, я бы это прочитал!
Я не думаю, что переключение между графиками и сеансами может быть очень быстрым.