Tensorflow: как заменить node на графике расчета?
Если у вас есть два непересекающихся графика и вы хотите связать их, включите это:
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
node? Или вы должны думать об этом перед построением графика?
Ответы
Ответ 1
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"]
Ответ 2
Если вы хотите объединить подготовленные модели (например, повторно использовать части предварительно обработанной модели в новой модели), вы можете использовать Saver
для сохранения контрольной точки первой модели, затем восстановить эту модель (полностью или частично ) в другую модель.
Например, скажем, вы хотите повторно использовать вес модели 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.
Ответ 3
Оказывается, что tf.train.import_meta_graph
передает все дополнительные аргументы базовому import_scoped_meta_graph
, у которого есть аргумент input_map
, и использует его, когда получает доступ к собственному (внутреннему) вызову import_graph_def
.
Это не задокументировано, и он взял меня waaaay много времени, чтобы найти его, но он работает!