TensorFlow學習(三):Graph和Session
更新時間:
2017.5.5
對一些函式或者類有了新的認識。重要的地方修改一下。
簡化了大量的東西,保留重點,只寫了常用函式的用法,其他的根據需要看文件
之前講完變數常量等等基本量的操作,意味著最基本的東西都有了,然後接下來很重要的就是那些量和操作怎麼組成更大的集合,怎麼執行這個集合。這些就是計算圖譜Graph和Session的作用了。
一.Graph
首先官方文件地址:tf.Graph
這裡僅列出了最基本和頻繁使用的函式,更多特定的需要請參考文件。
Ⅰ.介紹
一個TensorFlow的運算,被表示為一個數據流的圖。
一幅圖中包含一些操作(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())
另外一種典型的用法就是要使用到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)
結果:
上面的例子裡面創建立了一個新的圖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].
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())
c = tf.constant(...)
sess = tf.Session()
with sess.as_default():
print(c.eval())
# ...
with sess.as_default():
print(c.eval())