2015-11-17 5 views
21

Если у вас есть две пересекающиеся графики, и я хочу связать их, превращая это:Tensorflow: как заменить узел на графике вычисления?

x = tf.placeholder('float') 
y = f(x) 

y = tf.placeholder('float') 
z = f(y) 

в этом:

x = tf.placeholder('float') 
y = f(x) 
z = g(y) 

Есть ли способ сделать это? Похоже, что в некоторых случаях это может сделать конструкцию проще.

Например, если у вас есть график, который имеет входное изображение как tf.placeholder, и вы хотите оптимизировать входное изображение, стиль глубокой мечты, есть ли способ заменить местозаполнитель узлом tf.variable? Или вы должны думать об этом, прежде чем строить график?

ответ

18

TL; DR: Если вы можете определить два вычисления как функции Python, вы должны это сделать. Если вы не можете, в TensorFlow есть более расширенные функции для сериализации и импорта графиков, что позволяет составлять графики из разных источников.

Один из способов сделать это в TensorFlow, чтобы построить непересекающиеся вычисления в виде отдельных tf.Graph объектов, а затем преобразовать их в последовательную форму буферов протокола с помощью Graph.as_graph_def():

with tf.Graph().as_default() as g_1: 
    input = tf.placeholder(tf.float32, name="input") 
    y = f(input) 
    # NOTE: using identity to get a known name for the output tensor. 
    output = tf.identity(y, name="output") 

gdef_1 = g_1.as_graph_def() 

with tf.Graph().as_default() as g_2: # NOTE: g_2 not g_1  
    input = tf.placeholder(tf.float32, name="input") 
    z = g(input) 
    output = tf.identity(y, name="output") 

gdef_2 = g_2.as_graph_def() 

Тогда вы могли бы составить gdef_1 и gdef_2 в третьем графике , используя tf.import_graph_def():

with tf.Graph().as_default() as g_combined: 
    x = tf.placeholder(tf.float32, name="") 

    # Import gdef_1, which performs f(x). 
    # "input:0" and "output:0" are the names of tensors in gdef_1. 
    y, = tf.import_graph_def(gdef_1, input_map={"input:0": x}, 
          return_elements=["output:0"]) 

    # Import gdef_2, which performs g(y) 
    z, = tf.import_graph_def(gdef_2, input_map={"input:0": y}, 
          return_elements=["output:0"] 
+0

Есть ли причина, по которой я не могу тренироваться с использованием результатов вышеизложенного, т. Е. Что-то вроде 'tf.train.AdamOptimizer(). Minim (tf.nn.l2_loss (z-x))'? Я получаю что-то вроде «Нет переменных для оптимизации» – bge0

+3

Это, к сожалению, правильно. Обходной путь состоит в том, чтобы сделать 'vars = op.outputs [0] для op в tf.get_default_graph(). Get_operations(), если op.type ==" Variable "]', а затем передать var_list = vars' для 'minim()' , – mrry

+0

Спасибо за быстрый ответ! В вашем примере для 'y = f (input)' Я пробовал просто использовать 'tf.mul (w, input)' где 'w ~ N (0, 0.01)' [т.е. tf.Variable]. Используя коллекцию переменных, я вижу сбор 'w', но все равно получаю эту ошибку:' TypeError: Argument не является tf.Variable: Tensor ("import/w: 0", dtype = float32_ref) ' – bge0

3

Если вы хотите совместить обученные модели (например, для повторного использования частей pretrained модели в новой модели), у ou может использовать Saver для сохранения контрольной точки первой модели, а затем восстановить эту модель (полностью или частично) в другую модель.

Например, скажем, вы хотите использовать вес модели 1 в w в модели 2, а также конвертировать x из заменителя переменный:

with tf.Graph().as_default() as g1: 
    x = tf.placeholder('float') 
    w = tf.Variable(1., name="w") 
    y = x * w 
    saver = tf.train.Saver() 

with tf.Session(graph=g1) as sess: 
    w.initializer.run() 
    # train... 
    saver.save(sess, "my_model1.ckpt") 

with tf.Graph().as_default() as g2: 
    x = tf.Variable(2., name="v") 
    w = tf.Variable(0., name="w") 
    z = x + w 
    restorer = tf.train.Saver([w]) # only restore w 

with tf.Session(graph=g2) as sess: 
    x.initializer.run() # x now needs to be initialized 
    restorer.restore(sess, "my_model1.ckpt") # restores w=1 
    print(z.eval()) # prints 3. 
+0

Исправьте меня, если я «Неправильно, но этот подход не сохраняет структуру вашего графика, поэтому вам нужно переопределять каждый раз, когда вы хотите использовать переменные. – Pietrko

3

Оказывается, что tf.train.import_meta_graph передает все дополнительные аргументы в основном import_scoped_meta_graph, который имеет аргумент input_map и использует его, когда он добирается до своего собственного (внутреннего) вызова import_graph_def.

Это не задокументировано, и я взял waaaay toooo много времени, чтобы найти его, но он работает!

+0

Большое спасибо, у меня есть такой ответ в течение длительного времени. – Tom