转自https://blog.csdn.net/xierhacker/article/details/53860379
之前讲完变量常量等等基本量的操作,意味着最基本的东西都有了,然后接下来很重要的就是那些量和操作怎么组成更大的集合,怎么运行这个集合。这些就是计算图谱Graph和Session的作用了。
因为篇幅和格式的缘故,这里的测试代码并没写全,全部的代码可以在我的GitHub上面找到:LearningTensorFlow/3.Graph_and_Session/
一.Graph
首先官方文档地址:tf.Graph
这里仅列出了最基本和频繁使用的函数,更多特定的需要请参考文档。
Ⅰ.介绍
一个TensorFlow的运算,被表示为一个数据流的图。
一幅图中包含一些操作(Operation)对象,这些对象是计算节点。前面说过的Tensor对象,则是表示在不同的操作(operation)间的数据节点
你一旦开始你的任务,就已经有一个默认的图已经创建好了。而且可以通过调用tf.get_default_graph()
来访问到。
添加一个操作到默认的图里面,只要简单的调用一个定义了新操作的函数就行。比如下面的例子展示的:
import tensorflow as tf
import numpy as np
c=tf.constant(value=1)
#print(assert c.graph is tf.get_default_graph())
print(c.graph)
print(tf.get_default_graph())
- 1
另外一种典型的用法就是要使用到Graph.as_default()
的上下文管理器( context manager),它能够在这个上下文里面覆盖默认的图。如下例
import tensorflow as tf
import numpy as np
c=tf.constant(value=1)
#print(assert c.graph is tf.get_default_graph())
print(c.graph)
print(tf.get_default_graph())
g=tf.Graph()
print("g:",g)
with g.as_default():
d=tf.constant(value=2)
print(d.graph)
#print(g)
g2=tf.Graph()
print("g2:",g2)
g2.as_default()
e=tf.constant(value=15)
print(e.graph)
- 1
结果:
上面的例子里面创创建了一个新的图g,然后把g设为默认,那么接下来的操作不是在默认的图中,而是在g中了。你也可以认为现在g这个图就是新的默认的图了。
要注意的是,最后一个量e不是定义在with语句里面的,也就是说,e会包含在最开始的那个图中。也就是说,要在某个graph里面定义量,要在with语句的范围里面定义。
一个Graph的实例支持任意多数量通过名字区分的的“collections”。
为了方便,当构建一个大的图的时候,collection能够存储很多类似的对象。比如 tf.Variable就使用了一个collection(tf.GraphKeys.GLOBAL_VARIABLES),包含了所有在图创建过程中的变量。
也可以通过之指定新名称定义其他的collection
Ⅱ.属性
building_function:Returns True iff this graph represents a function.
finalized:返回True,要是这个图被终止了
graph_def_versions:The GraphDef version information of this graph.
seed:The graph-level random seed of this graph.
version:Returns a version number that increases as ops are added to the graph.
Ⅲ.函数
__init__()
作用:创建一个新的,空的图
add_to_collection(name,value)
作用:存放值在给定名称的collection里面(因为collection不是sets,所以有可能一个值会添加很多次)
参数:
name: The key for the collection. The GraphKeys class contains many standard names for collections.
value: 添加到collection中的值
as_default()
作用:
返回一个上下文管理器,使得这个Graph对象成为当前默认的graph.当你想在一个进程里面创建多个图的时候,就应该使用这个函数.为了方便起见,一个全局的图对象被默认提供,要是你没有显式创建一个新的图的话,所有的操作(ops)都会被添加到这个默认的图里面来.
通过with关键字和这个方法,来让这个代码块内创建的从操作(ops)添加到这个新的图里面.
默认的是当前线程的”property”,如果你创建了一个新的线程而且想使用这个默认的图,你应该显式添加一个g.as_default():
在这个线程函数里面.
下面是两种写法示例:
# 1. Using Graph.as_default():
g = tf.Graph()
with g.as_default():
c = tf.constant(5.0)
assert c.graph is g
# 2. Constructing and making default:
with tf.Graph().as_default() as g:
c = tf.constant(5.0)
assert c.graph is g
device(*args,**kwds)
作用:
返回一个上下文管理器(context manager)指定新创建的操作(ops)默认使用的设备。
参数:
device_name_or_function::在这个上下文下面使用的设备名称或者函数。这个参数可以十一个设备名称字符串,或者十一个设备函数,或者是None。如果是设备名称字符串,那么所有的在这个上下问构建的操作(operations)都会被指派给这个名字的设备。unless overridden by a nested device() context.
如果是一个函数,他会被当做十一个从操作对象到设备字符串的函数。每次一个新的操作生成,都会被激活,这个操作就会被只拍到函数返回的设备名称上面。
If it is None, all device() invocations from the enclosing context will be ignored.
For information about the valid syntax of device name strings, see the documentation in DeviceNameUtils.
例子:
with g.device('/gpu:0'):
# All operations constructed in this context will be placed
# on GPU 0.
with g.device(None):
# All operations constructed in this context will have no
# assigned device.
# Defines a function from `Operation` to device string.
def matmul_on_gpu(n):
if n.type == "MatMul":
return "/gpu:0"
else:
return "/cpu:0"
with g.device(matmul_on_gpu):
# All operations of type "MatMul" constructed in this context
# will be placed on GPU 0; all other operations will be placed
# on CPU 0.
finalize()
作用:结束这个graph,使得他只读(read-only).调用 g.finalize()之后,新的操作就不能够添加到g里面去了.这个函数是保证党图被多个线程共用的时候,没有新的操作能够添加进去.比如:tf.train.QueueRunner.
get_all_collection_keys()
作用:
返回在graph中使用的collection列表
get_operation_by_name(name)
作用:对于给定的名称,返回操作(Operation)
参数:
name: 操作名称
get_operations()
作用:
返回图中操作的列表。
get_tensor_by_name(name)
作用:返回给定名称的tensor
is_feedable(tensor)
作用:要是一个tensor能够被feed的话,返回True。
is_fetchable(tensor_or_op)
作用:要是tensor或者op能够取到,返回True
name_scope(*args,**kwds)
Returns a context manager that creates hierarchical names for operations.
A graph maintains a stack of name scopes. A with name_scope(…): statement pushes a new name onto the stack for the lifetime of the context.
The name argument will be interpreted as follows:
A string (not ending with ‘/’) will create a new name scope, in which name is appended to the prefix of all operations created in the context. If name has been used before, it will be made unique by calling self.unique_name(name).
A scope previously captured from a with g.name_scope(…) as scope: statement will be treated as an “absolute” name scope, which makes it possible to re-enter existing scopes.
A value of None or the empty string will reset the current name scope to the top-level (empty) name scope.
For example:
with tf.Graph().as_default() as g:
c = tf.constant(5.0, name="c")
assert c.op.name == "c"
c_1 = tf.constant(6.0, name="c")
assert c_1.op.name == "c_1"
# Creates a scope called "nested"
with g.name_scope("nested") as scope:
nested_c = tf.constant(10.0, name="c")
assert nested_c.op.name == "nested/c"
# Creates a nested scope called "inner".
with g.name_scope("inner"):
nested_inner_c = tf.constant(20.0, name="c")
assert nested_inner_c.op.name == "nested/inner/c"
# Create a nested scope called "inner_1".
with g.name_scope("inner"):
nested_inner_1_c = tf.constant(30.0, name="c")
assert nested_inner_1_c.op.name == "nested/inner_1/c"
# Treats `scope` as an absolute name scope, and
# switches to the "nested/" scope.
with g.name_scope(scope):
nested_d = tf.constant(40.0, name="d")
assert nested_d.op.name == "nested/d"
with g.name_scope(""):
e = tf.constant(50.0, name="e")
assert e.op.name == "e"
The name of the scope itself can be captured by with g.name_scope(…) as scope:, which stores the name of the scope in the variable scope. This value can be used to name an operation that represents the overall result of executing the ops in a scope. For example:
inputs = tf.constant(…)
with g.name_scope(‘my_layer’) as scope:
weights = tf.Variable(…, name=”weights”)
biases = tf.Variable(…, name=”biases”)
affine = tf.matmul(inputs, weights) + biases
output = tf.nn.relu(affine, name=scope)
NOTE: This constructor validates the given name. Valid scope names match one of the following regular expressions:
[A-Za-z0-9.][A-Za-z0-9_.\-/]* (for scopes at the root)
[A-Za-z0-9_.\-/]* (for other scopes)
Args:
name: A name for the scope.
Returns:
A context manager that installs name as a new name scope.
Raises:
ValueError: If name is not a valid scope name, according to the rules above.
prevent_feeding
二.Session(tf.Session)
运行TensorFLow操作(operations)的类,一个Seesion包含了操作对象执行的环境.
一个例子:
# -*- coding: utf-8 -*-
from __future__ import print_function,division
import tensorflow as tf
#build graph
a=tf.constant(2.)
b=tf.constant(5.)
c=a*b
#construct session
sess=tf.Session()
#Evaluate the tensor `c`
print(sess.run(c))
#close session
sess.close()
上面最后一句close()是因为session一般都拥有很多的资源,要是session不再可用的话,就要调用close()函数来释放这些资源。
简单一点的话,也可以用上下文管理器,比如参照下面的方式:
# Using the `close()` method.
sess = tf.Session()
sess.run(...)
sess.close()
# Using the context manager.
with tf.Session() as sess:
sess.run(...)
属性
graph:“投放”到session中的图
graph_def:图的描述
sess_str
重要函数:
tf.Session.__init__
(target=”, graph=None, config=None)
作用:
这是session的构造函数,创建一个新的tensorflow的session参数:
target:(可选)连接的执行引擎,默认是使用in-process引擎,分布式TensorFLow有更多的例子。
graph: (可选)投放进的计算图(graph),要是没有指定的话,那么默认的图就会被投放到这个session。要是你在同一个进程里面用了很多的图,你将为各个图使用不用的session,但是每一个graph都能够在多个session中使用。在这种情况下,经常显式的传递graph参数到session的构造里面。
config: (可选) A ConfigProto protocol buffer with configuration options for the session.
tf.Session.run(fetches, feed_dict=None, options=None, run_metadata=None)
作用:
运行操作估算(计算)tensor。
参数:
fetches: 一个单独的图的元素,或者一个图的元素的列表。或者一个字典,这个字典的值是刚刚所说的一个图的元素(元素列表)(见下面第四部分的例子)。图的元素可以是一个操作(那么fetch回来的值将是None);一个tensor(反回的值将是将是表示这个tensor值的numpy ndarray对象);一个sparsetensor(稀疏tensor);一个get_tensor_handle的操作;一个表示tensor或者操作名称的string
feed_dict: 一个字典,为之前“占位”的元素“喂”给值。(具体见第四部分的例子。)
The optional feed_dict argument allows the caller to override the value of tensors in the graph. Each key in feed_dict can be one of the following types:
If the key is a Tensor, the value may be a Python scalar, string, list, or numpy ndarray that can be converted to the same dtype as that tensor. Additionally, if the key is a placeholder, the shape of the value will be checked for compatibility with the placeholder.
If the key is a SparseTensor, the value should be a SparseTensorValue.
If the key is a nested tuple of Tensors or SparseTensors, the value should be a nested tuple with the same structure that maps to their corresponding values as above.
Each value in feed_dict must be convertible to a numpy array of the dtype of the corresponding key.
options: A [RunOptions] protocol buffer
run_metadata: A [RunMetadata] protocol buffer
返回值:
如果你的fetchs参数传入的图的一个元素,那么返回一个单独的值,要是是图的一个元素列表,那么返回就是一个列表,要是你传入的是一个字典,那么返回的也是一个字典,这个字典的键和你传入的字典的键是一样的。函数返回的值和你传进去的fetch参数的形状是一样的,只是里面的元素是相应的值而已了。
The optional options argument expects a [RunOptions] proto. The options allow controlling the behavior of this particular step (e.g. turning tracing on).
The optional run_metadata argument expects a [RunMetadata] proto. When appropriate, the non-Tensor output of this step will be collected there. For example, when users turn on tracing in options, the profiled info will be collected into this argument and passed back.
Example:
a = tf.constant([10, 20])
b = tf.constant([1.0, 2.0])
# 'fetches' can be a singleton
v = session.run(a)
# v is the numpy array [10, 20]
# 'fetches' can be a list.
v = session.run([a, b])
# v a Python list with 2 numpy arrays: the numpy array [10, 20] and the
# 1-D array [1.0, 2.0]
# 'fetches' can be arbitrary lists, tuples, namedtuple, dicts:
MyData = collections.namedtuple('MyData', ['a', 'b'])
v = session.run({'k1': MyData(a, b), 'k2': [b, a]})
# v is a dict with
# v['k1'] is a MyData namedtuple with 'a' the numpy array [10, 20] and
# 'b' the numpy array [1.0, 2.0]
# v['k2'] is a list with the numpy array [1.0, 2.0] and the numpy array
# [10, 20].
- 1
tf.Session.close()
作用:关闭这个session,调用这个函数会使得所有与这个session有关的资源被释放
as_default()
作用:返回一个上下文管理器,使得这个对象成为当前默认的session/使用with关键字然后可以在with关键字代码块中执行tf.Operation.run和 tf.Tensor.eval ,都是默认在当前session下面执行。
c = tf.constant(..)
sess = tf.Session()
with sess.as_default():
assert tf.get_default_session() is sess
print(c.eval())
- 1
c = tf.constant(...)
sess = tf.Session()
with sess.as_default():
print(c.eval())
# ...
with sess.as_default():
print(c.eval())