0.TensorFlow的基礎模型:
|- 計算模型:計算圖
|- 數據模型:張量
|- 運行模型:會話
1.計算模型——計算圖:
1.1 計算圖的概念
計算圖,又稱爲“張量流圖”(TensorFlow的字面意思就是“張量流”)。用來描述張量(在TensorFlow中作爲一種基本數據結構,可以簡單的理解爲多維數組)之間通過計算相互轉化的過程。所以TensorFlow是一個通過計算圖的形式來表述計算的編程系統。TensorFlow中的每一個計算都是計算圖上的一個節點。節點之間的邊描述的是計算之間的依賴關係。TensorBoard是TensorFlow的可視化工具,可以用來繪製計算圖。
1.2 一次計算
1.2.1 完整代碼:
>>> import tensorflow as tf
>>> a = tf.constant([1.0,2.0], name="a")
>>> b = tf.constant([2.0,3.0], name="b")
>>> result = a + b
>>> sess = tf.Session()
2018-11-08 07:24:51.866562: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
>>> sess.run(result)
array([3., 5.], dtype=float32)
1.2.2 一次計算
|- 定義計算
|- 執行計算
1.2.3 定義計算:此過程會將定義的計算轉化成計算圖上的節點。
>>> import tensorflow as tf # 爲了簡潔,導入模塊時,指定其簡稱。類似於標準SQL語句中的“as”
>>> a = tf.constant([1.0,2.0], name="a")
>>> b = tf.constant([2.0,3.0], name="b")
>>> result = a + b
1.2.4 執行計算:
>>> sess = tf.Session()
>>> sess.run(result)
1.2.5 默認計算圖:
系統會自動維護一個默認的計算圖,通過tf.get_default_graph函數可以獲取當前默認的計算圖。
1.2.6 獲取張量x所屬計算圖:x.graph
>>> print(a.graph is tf.get_default_graph())
True
# 通過a.graph 可以查看張量所屬的計算圖。因爲我們沒有指定,所以這個計算圖應該等於當前默認的計算圖。所以上面操作返回值爲“True”。
1.3 生成計算圖
可以使用tf.Graph函數來生成新的計算圖。不同計算圖上的張量和運算都不會共享。
import tensorflow as tf
# 定義g1,v的初值設置爲“0”
g1 = tf.Graph()
with g1.as_default():
v = tf.get_variable("v", shape=[1], initializer=tf.zeros_initializer)
# 定義g2,v的初值設置爲“1”
g2 = tf.Graph()
with g2.as_default():
v = tf.get_variable("v", shape=[1], initializer=tf.ones_initializer)
# 在計算圖g1中讀取變量“v”的取值
with tf.Session(graph=g1) as sess:
tf.global_variables_initializer().run()
with tf.variable_scope("", reuse=True):
print(sess.run(tf.get_variable("v")))
# 在計算圖g2中讀取變量“v”的取值
with tf.Session(graph=g2) as sess:
tf.global_variables_initializer().run()
with tf.variable_scope("", reuse=True):
print(sess.run(tf.get_variable("v")))
運行:
>>> import tensorflow as tf
>>> g1 = tf.Graph()
>>> with g1.as_default():
... v = tf.get_variable("v", shape=[1], initializer=tf.zeros_initializer)
...
>>>
>>>
>>> with tf.Session(graph=g1) as sess:
... tf.global_variables_initializer().run()
... with tf.variable_scope("", reuse=True):
... print(sess.run(tf.get_variable("v")))
...
[ 0.]
>>> g2 = tf.Graph()
>>> with g2.as_default():
... v = tf.get_variable("v", shape=[1], initializer=tf.ones_initializer)
...
>>>
>>> with tf.Session(graph=g2) as sess:
... tf.global_variables_initializer().run()
... with tf.variable_scope("", reuse=True):
... print(sess.run(tf.get_variable("v")))
...
[ 1.]
1.4 計算圖的基本功能:
|- 1.隔離張量和計算
|- 2.管理張量和計算
|- 3.指定運行計算的設備:計算圖可以通過tf.Graph.device 函數指定運行計算的設備。
例如:
g = tf.Graph()
# 指定計算運行的設備
with g.device('/gpu:0'):
result = a + b
|-4.計算圖的資源管理:計算圖可以通過集合(collection)來管理不同類型的資源。
|- 將資源加入一個或多個集合:tf.add_to_collection
|- 獲取一個集合中的所有資源:tf.get_collection
|- 這裏的資源包括:張量、變量、運行TensorFlow程序所需的隊列資源等
|- 爲了方便使用,TensorFlow自動管理了一些常用集合:
|- tf.GraphKeys.VARIABLES;所有變量;用於持久化TensorFlow模型。
|- tf.GraphKeys.TRAINABLE.VARIABLES;可學習的變量(一般指神經網絡中的參數);用於模型訓練、生成模型可視化內容。
|- tf.GraphKeys.SUMMARIES;日誌生成相關的張量;用於TensorFlow計算可視化。
|- tf.GraphKeys.QUEUE_RUNNERS;處理輸入的QueueRunner;用於輸入處理
|- tf.GraphKeys.MOVING_AVERAGE_VARIABLES;所有計算了滑動平均值的變量;用於計算變量的滑動平均值
2.數據模型——張量
2.1 張量的概念
在TensorFlow中,所有的數據都通過張量的形式來表示。
功能角度:可以理解爲多維數組。
|- 零階張量表示標量(scalar),也就是一個數;
|- 一階張量表示向量(vector),也就是一個一維數組;
|- 第n階張量可以理解爲一個n維數組。
2.2 張量中存儲內容的實質
張量中存儲的內容並不是數組,它只是對TensorFlow中運算結果的引用。在張量中並沒有真正保存數字,它保存的是如何得到這些數字的計算過程。例如:
import tensorflow as tf
# tf.constant 是一個計算,這個計算的結果爲一個張量,保存在變量a中
a = tf.constant([1.0,2.0], name="a")
b = tf.constant([2.0,3.0], name="b")
result = tf.add(a, b, name="add")
print result
輸出:
Tensor("add:0", shape=(2,), dtype=float32)
2.3 張量的結構
從上面的輸出內容“Tensor("add:0", shape=(2,), dtype=float32)”看出,張量中保存了名字(name),維度(shape)和類型(type)。
|- 名字(name):
|- 一個張量的唯一標識符
|- 該張量是如何計算出來的
|- 張量的名字的組成:node:src_output_number。(add:0,表示該“result”張量是計算節點“add”輸出的第一個結果)
|- 維度(shape)
|- 描述該張量的維度信息。(shape=(2,)表示該張量是一個一維數組,這個數組的長度爲2)
|- 類型(type)
|- 每個張量都會有一個唯一的類型
|- 指張量所表示的數組的數據類型
|- 不同類型的張量之間運算會報錯:類型不匹配
2.4 張量的創建
創建張量:
# 1.定義一個浮點型張量
a = tf.constant([1.0, 2.0], name="a", dtype=tf.float32)
# 2.定義一個浮點型張量
a = tf.constant([1, 2], name="a", dtype=tf.float32)
# 3.定義一個浮點型張量
a = tf.constant([1.0, 2.0], name="a")
# 4.定義一個整型張量
a = tf.constant([1, 2], name="a", dtype=tf.int32)
# 5.定義一個整型張量
a = tf.constant([1, 2], name="a")
不指定類型,系統會根據輸入的數組數據類型來推斷數據類型。不帶小數點,被推斷爲int32;帶有小數點,被推斷爲float32。
2.5 張量的數據類型
TensorFlow支持14種數據類型:
|- 字符串
|- tf.string
|- 布爾型
|- tf.bool
|- 整型
|- tf.int8
|- tf.int16
|- tf.int32
|- tf.int64
|- tf.uint8
|- tf.uint16
|- 浮點型
|- tf.float16
|- tf.float32
|- tf.float64
|- tf.double
|- 複數
|- tf.complex64
|- tf.complex128
2.6 張量的創建
創建張量的用途:
|- 1.表示中間結果,用以提高代碼的可讀性;
|- 2.表示最終結果,用來獲取程序的最終結果:tf.Session().run(result).
3.運行模型——會話
3.1 會話的功能:
|- 執行定義好的運算
|- 擁有並管理TensorFlow程序運行時的所有資源
|- 計算結束之後,需要關閉會話來幫助系統回收資源,否則會造成資源泄露
3.2 會話的模式
模式一:
# 創建一個會話
sess = tf.Session()
# 使用這個創建好的會話來得到關心的運算的結果。如前面的:sess.run(result)
sess.run(...)
# 關閉會話,釋放資源
sess.close()
模式二:
# 創建一個會話,並通過Python中的上下文管理器來管理這個會話。將所有計算放在with內即可。
with tf.Session() as sess:
# 使用創建好的會話來計算關心的結果
sess.run(...)
# 不需要再調用“Session.close”函數來關閉會話,當上下文退出時 自動關閉會話並釋放資源。
對比:
|- 模式一:當程序因異常退出時,後面關閉會話的函數(sess.close())可能就不會被執行,那麼可能造成資源泄露。
|- 模式二:不存在忘記關閉會話的問題,不存在異常退出導致的資源泄露問題。
(推薦模式二,注意縮進即可。)
3.3 默認會話
通過設定默認會話並計算張量的取值
# 方法一
sess = tf.Session() # 獲取一個會話
with sess.as_default(): # 將獲取的會話設置爲默認會話
print(result.eval()) # 用默認會話計算出result張量並輸出
# 方法二
sess = tf.Session() # 獲取一個會話
print(sess.run(result)) # 以指定的會話計算出result張量並輸出
# 方法三
sess = tf.Session() # 獲取一個會話
print(result.eval(session=sess)) # 以指定的會話計算出result張量並輸出
3.4 直接構建默認會話
sess = tf.InteractiveSession() # 生成交互式會話,並將其註冊爲默認會話(在交互式環境中可用)
print(result.eval())
sess.close()
功能上:tf.Session().as_default() = tf.InteractiveSession()
3.5 配置會話
通過ConfigProto配置會話:
# 配置會話的屬性
config = tf.ConfigProto(allow_soft_placement=True,log_device_placement=True)
# 用上面配置好的配置來創建一個交互式會話
sess1 = tf.InteractiveSession(config=config)
# 用上面配置好的配置來創建一個會話
sess2 = tf.Session(config=config)
參數包含並行的線程數、GPU分配策略、運算超時時間等。
最常用的是allow_soft_placement和log_device_placement。
|- 允許軟放置allow_soft_placement:Boolean,默認爲False。
|- 意義:當此參數取“True”時,以下情況中GPU上的運算可以放在CPU上進行計算。提高代碼的可移植性。
|- 1. 運算無法在GPU上執行;
|- 2.GPU資源不足;
|- 3.運算輸入包含對CPU結果的引用。
|- 允許將計算在設備中的分佈記錄至日誌log_device_placement:Boolean,默認爲False。
|- 意義:當此參數取“True”時,日誌中將會記錄每個節點(計算)被安排到哪個設備上以方便調試。在生產環境將此參數設置爲“False”以減少日誌量。