Инициализация переменных в соединенных графах тензорных потоков

Я пытаюсь объединить несколько моделей Tensorflow на отдельных графиках в одну модель на одном графике (я предполагаю, что типичными сценариями будут модели передачи обучения, ансамбли и т. д., которые необходимо заморозить).

Я могу соединить два графика с помощью tf.import_graph_def. Однако, когда один из исходных графиков содержит переменную, я не могу ввести в нее значения на новом графике. Операции назначения копируются как часть графа, и если я запускаю их вручную, я получаю ожидаемые результаты. (Раскомментировать sess.run-вызов в четвертом with graph...-блоке)

import tensorflow as tf

graph1 = tf.Graph()
with graph1.as_default():
    with tf.Session(graph=graph1) as sess:
        var1 = tf.Variable([1, 1, 1], name='var1')
        tensor1 = tf.multiply(var1, 2, name='tensor1')

graph2 = tf.Graph()
with graph2.as_default():
    with tf.Session(graph=graph2) as sess:
        placeholder = tf.placeholder(tf.int32, [3], name='placeholder')
        tensor2 = tf.multiply(placeholder, 2, name='tensor2')

graph3 = tf.Graph()
with graph3.as_default():
    with tf.Session(graph=graph3) as sess:
        graph1out, = tf.import_graph_def(graph1.as_graph_def(), name='graph1', return_elements=['tensor1:0'])
        tf.import_graph_def(graph2.as_graph_def(), name='graph2', input_map={'placeholder:0': graph1out})

with graph3.as_default():
    with tf.Session(graph=graph3) as sess:
        sess.run(tf.global_variables_initializer())
        #sess.run(graph3.get_tensor_by_name('graph1/var1/Assign:0'))
        tensor = graph3.get_tensor_by_name('graph2/tensor2:0')
        result = sess.run(tensor)

Запуск этого фрагмента как есть дает:

FailedPreconditionError (see above for traceback): Attempting to use uninitialized value graph1/var1

Ручной запуск assign-ops — это очень мало общего подхода, который будет грязно писать как часть общей функции. Это также требует, чтобы эти вызовы назначения выполнялись каждый раз, когда я повторно инициализирую сеанс с графом.

Есть ли более общий способ сделать это? Например, создавая новые переменные на основе старых и привязывая их к существующей структуре?

Если нет, есть ли способ обернуть вызовы назначения? Так что, по крайней мере, я могу запустить одну общую init-операцию вместо неизвестного количества конкретных для каждого случая?


person estenhl    schedule 13.07.2017    source источник


Ответы (1)


Исправлено это путем создания init-wrapper. Для всех тензоров с именами, оканчивающимися на «Apply:(int)», я использую tf.reduce_sum (для стандартизации их форм) и помещаю их в tf.stack. Эта операция инициализации внутренне обрабатывается как noop, но она гарантирует, что каждый переданный ей тензор будет запущен (и, таким образом, также инициализирует их соответствующую переменную). Семантически его можно рассматривать как tf.global_variables_initializer().

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

person estenhl    schedule 17.07.2017
comment
Я был бы признателен немного больше! - person MathiasOrtner; 06.11.2017
comment
было бы лучше, если бы вы поделились своими окончательными кодами - person Eliethesaiyan; 29.03.2018