График TensorFlow обычно создается постепенно с входов на выходы, а затем выполняется. Если посмотреть на код Python, списки входов операций являются неизменными, что предполагает, что входы не должны быть изменены. Означает ли это, что нет способа обновить/изменить существующий граф?
Возможно ли изменить существующий график вычислений TensorFlow?
Ответ 1
Класс TensorFlow tf.Graph
представляет собой структуру данных только для приложений, что означает, что вы можете добавлять узлы в график после выполнения части графика, но вы не может удалить или изменить существующие узлы. Поскольку TensorFlow выполняет только необходимый подграф, когда вы вызываете Session.run()
, не существует времени исполнения для резервирования узлов на графике (хотя они будут продолжать потреблять память).
Чтобы удалить все узлы в графе, вы можете создать сеанс с новым графиком:
with tf.Graph().as_default(): # Create a new graph, and make it the default.
with tf.Session() as sess: # `sess` will use the new, currently empty, graph.
# Build graph and execute nodes in here.
Ответ 2
Да, tf.Graph
создаются в виде добавления только, как это делает @mrry.
Но обходной путь:
Концептуально вы можете изменить существующий граф, клонировав его и выполнив необходимые изменения на этом пути. Начиная с r1.1, Tensorflow предоставляет модуль с именем tf.contrib.graph_editor
, который реализует вышеуказанную идею как набор удобных функций.
Ответ 3
В дополнение к тому, что говорят @zaxily и @mrry, я хочу привести пример того, как на самом деле сделать модификацию графа. Короче говоря:
- нельзя изменять существующие операции, все операции являются окончательными и неизменяемыми
- Можно скопировать операцию, изменить ее входные данные или атрибуты и добавить новую операцию обратно на график
- все последующие операции, которые зависят от новой/скопированной операции, должны быть воссозданы. Да, значительная часть графика будет скопирована, что не является проблемой
Код:
import tensorflow
import copy
import tensorflow.contrib.graph_editor as ge
from copy import deepcopy
a = tf.constant(1)
b = tf.constant(2)
c = a+b
def modify(t):
# illustrate operation copy&modification
new_t = deepcopy(t.op.node_def)
new_t.name = new_t.name+"_but_awesome"
new_t = tf.Operation(new_t, tf.get_default_graph())
# we got a tensor, let return a tensor
return new_t.outputs[0]
def update_existing(target, updated):
# illustrate how to use new op
related_ops = ge.get_backward_walk_ops(target, stop_at_ts=updated.keys(), inclusive=True)
new_ops, mapping = ge.copy_with_input_replacements(related_ops, updated)
new_op = mapping._transformed_ops[target.op]
return new_op.outputs[0]
new_a = modify(a)
new_b = modify(b)
injection = new_a+39 # illustrate how to add another op to the graph
new_c = update_existing(c, {a:injection, b:new_b})
with tf.Session():
print(c.eval()) # -> 3
print(new_c.eval()) # -> 42