如何不使用with-as语句向TensorFlow Graph添加操作?
关于TensorFlow中无需with语句向Graph添加节点的问题
嘿,这个问题问得挺到位的!先直接给你结论:TensorFlow里没有办法像你设想的那样,直接调用Graph对象的.add()方法把已经创建好的操作/张量“塞”到指定图里。
为什么不能这么做?
TensorFlow里的操作(Operation)和张量(Tensor)在创建的那一刻就已经绑定到了当前的默认图(default graph)上,它们的归属关系是初始化时就确定的,没法事后修改或者转移到另一个图中。这和Session的两种使用方式本质不同——Session的with语句只是帮你自动管理会话的开启和关闭,而Graph的as_default()上下文管理器是用来临时切换当前的默认图,让后续创建的所有节点自动归属到这个图里,两者的设计逻辑完全不一样。
关于你提到的“集合”方式
你想到的集合(collections)其实只是TensorFlow提供的一种节点归类管理工具,比如把所有变量放到tf.GraphKeys.GLOBAL_VARIABLES集合里方便批量初始化。但它并不能把原本属于其他图的节点“加入”到目标图的集合中——这些节点本身还是属于原来的图,强行加到其他图的集合里,后续在目标图中运行时肯定会报错。
不用with块的替代方案
如果你实在不想用with上下文块,其实还有两种方式可以实现类似效果,但本质上还是利用了默认图的切换逻辑:
- 使用装饰器:把创建节点的函数用目标图的
as_default()装饰,这样函数内部创建的节点都会自动归属到这个图:
import tensorflow as tf a_graph = tf.Graph() @a_graph.as_default() def create_test_nodes(): x = tf.placeholder(dtype=tf.float32, name='test') return x # 调用函数后,x就属于a_graph了 x = create_test_nodes()
- 手动管理上下文:直接调用上下文对象的
__enter__()和__exit__()方法,但这种方式不推荐,因为很容易忘记调用__exit__()导致上下文泄漏:
import tensorflow as tf a_graph = tf.Graph() graph_context = a_graph.as_default() # 进入上下文,此时默认图切换为a_graph graph_context.__enter__() # 在这里创建的所有节点都属于a_graph x = tf.placeholder(dtype=tf.float32, name='test') y = tf.multiply(x, 2.0) # 一定要退出上下文 graph_context.__exit__(None, None, None)
总结
本质上,TensorFlow的节点归属是创建时绑定的,没有事后添加的机制。最安全、简洁的方式还是官方推荐的with a_graph.as_default():上下文管理器,这也是TensorFlow设计的规范用法,尽量不要绕开它哦!
内容的提问来源于stack exchange,提问作者zwep
相关产品推荐
相关产品推荐

