TensorFlow 基本操作
Tensorflow基本概念
- 圖(Graph):圖描述了計算的過程,TensorFlow使用圖來表示計算任務。
- 張量(Tensor):TensorFlow使用tensor表示數據。每個Tensor是一個類型化的多維數組。
- 操作(op):圖中的節點被稱為op(opearation的縮寫),一個op獲得/輸入0個或多個Tensor,執行計算,產生0個或多個Tensor。
- 會話(Session):圖必須在稱之為“會話”的上下文中執行。會話將圖的op分發到諸如CPU或GPU之類的設備上執行。
- 變量(Variable):運行過程中可以被改變,用于維護狀態
邊的概念
TensorFlow的邊即有兩種連接關系:數據依賴,控制依賴。
- 實線邊表示數據依賴,代表數據,即張量。任意維度的數據統稱為張量。在機器學習算法中,張量在數據流圖中從前往后流一遍就完成一次前向傳播,而殘差從后向前流動一遍就完成一次反向傳播。
- 虛線邊表示控制依賴,可以用于控制操作的運行,這被用來確保happens-before關系,這類邊上沒有數據流過,但源節點必須在目的節點開始執行前完成。
Tensorflow數據屬性
| 數據類型 | Python類型 | 描述 |
| DT_FLOAT | tf.float32 | 32位浮點型 |
| DT_DOUBLE | tf.float64 | 64位浮點型 |
| DT_INT64 | tf.int64 | 64位有符號整型 |
| DT_INT32 | tf.int32 | 32位有符號整型 |
| DT_INT16 | tf.int16 | 16位有符號整型 |
| DT_INT8 | tf.int8 | 8位有符號整型 |
| DT_UNIT8 | tf.unit8 | 8位無符號整型 |
| DT_STRING | tf.string | 可變長度的字節數組,每一個張量元素是一個字節數組 |
| DT_BOOL | tf.bool | 布爾型 |
| DT_COMPLEX64 | tf.complex64 | 由兩個32位浮點數組成的復數:實部和虛部 |
| DT_QINT32 | tf.qint32 | 用于量化操作的32 位有符號整型 |
| DT_QINT8 | tf.qint8 | 用于量化操作的8 位有符號整型 |
| DT_QUINT8 | ?tf.quint8 | 用于量化操作的8 位無符號整型 |
節點
節點又稱為算子,它代表一個操作,一般用來表示施加的數字運算,也可以表示數據輸入的起點以及輸出的重點,或者是讀取/寫出持久化變量的終點
| 類別 | 示例 |
| 數學運算操作 | Add、Subtract、Multiply、Div、Exp、Log、Greater、Less、Equal ... |
| 數組運算操作 | Concat、Slice、Split、Constant、Rank、Shape、Shuffle ... |
| 矩陣運算操作 | MatMul、MatrixInverse、MatrixDeterminant … |
| 有狀態的操作 | Variable、Assign、AssignAdd … |
| 神經網絡構建操作 | SoftMax、Sigmoid、ReLU、Convolution2D、MaxPool … |
| 檢查點操作 | Save、Restore |
| 隊列和同步操作 | Enqueue、Dequeue、MutexAcquire、MutexRelease … |
| 控制張量流動的操作 | Merge、Switch、Enter、Leave、NextIteration |
使用Tensorflow必須理解下列概念:
TensorFlow可以認為是一種編程工具,使用TensorFlow來實現具體的業務需求,所以我們可以認為TensorFlow就是一個“工具箱”,然后我們使用TensorFlow這個“工具箱”中的各種“工具”(方法/API)來實現各種功能,比如使用TensorFlow實現基本的數值計算、機器學習、深度學習等;使用TensorFlow必須理解下列概念
- 使用圖(graph)來表示計算任務;
- 在會話(session)的上下文中執行圖;
- 使用tensor表示數據;
- 通過變量(Variable)來維護狀態 ;
- 使用feed和fetch可以為任意的操作(Operation/op)賦值或者從其中獲取數據。
TensorFlow 的程序一般分為兩個階段:構建階段 和 執行階段:
- 構建階段:op的執行步驟被描述稱為一個圖,然后使用 TensorFlow 提供的API構建這個 圖。
- 執行階段:將構建好的執行圖(Operation Graph)在給定的 會話 中執行,并得到執行結果。
圖(Graph)
TensorFlow 編程的重點是根據業務需求,使用 TensorFlow 的API將業務轉換為執行圖(有向無環圖)。
圖中的節點是Tensor,節點之間的連線是節點之間的操作,連線前的節點可以認為是操作的輸入,連線后的節點可以認為操作的輸出;根據節點的特性(是否有輸入輸出),可以將節點分為源節點、中間節點和最終的結果節點。
圖構建的第一步就是創建源op(source op); 源op不需要任何的輸入。op構造器的返回值代表被構造出的op的輸出,這些返回值可以傳遞給其它op構造器作為輸入或者直接獲取結果。
TensorFlow 庫中有一個默認圖(default graph),op構造器可以直接為其添加節點,一般情況下,使用默認的Graph即可完成程序代碼的實現。不過 TensorFlow 也支持通過Graph類管理多個圖。
使用默認圖
import tensorflow as tf# 1. 定義常量矩陣a和矩陣b # name屬性只是給定這個操作一個名稱而已 # 如果給定[[1, 2], [3, 4]],形狀已定,可以不指定shape參數 a = tf.constant([[1, 2], [3, 4]], dtype=tf.int32, name='a') print(type(a)) # 如果給定[5, 6, 7, 8],后面可以通過參數shape來確定形狀 b = tf.constant([5, 6, 7, 8], dtype=tf.int32, shape=[2, 2], name='b')# 2. 以a和b作為輸入,進行矩陣的乘法操作 c = tf.matmul(a, b, name='matmul') print(type(c))# 3. 以a和c作為輸入,進行矩陣的相加操作 g = tf.add(a, c, name='add') print(type(g))print("變量a是否在默認圖中:{}".format(a.graph is tf.get_default_graph()))不使用默認圖
注意:操作必須屬于同一個圖,不同圖中的節點不能相連
# 使用新的構建的圖 graph = tf.Graph() with graph.as_default():# 此時在這個代碼塊中,使用的就是新的定義的圖graph(相當于把默認圖換成了graph)d = tf.constant(5.0, name='d')print("變量d是否在新圖graph中:{}".format(d.graph is graph))with tf.Graph().as_default() as g2:e = tf.constant(6.0)print("變量e是否在新圖g2中:{}".format(e.graph is g2))# 這段代碼是錯誤的用法,記住:不能使用兩個圖中的變量進行操作,只能對同一個圖中的變量對象(張量)進行操作(op) # f = tf.add(d, e) # 報出:Tensor("Const:0", shape=(), dtype=float32) must be from the same graph as Tensor("d:0", shape=(), dtype=float32).會話(Session)
當執行圖構建完成后,才能啟動圖,進入到執行階段;啟動圖的第一步就是創建一個 Session 對象,如果無任何參數的情況下,會話構造器將啟動默認圖。
Session 會話
# 會話構建&啟動(默認情況下(不給定Session的graph參數的情況下),創建的Session屬于默認的圖) sess = tf.Session() result = sess.run(fetches=[c]) # result = sess.run(fetches=[c, g]) print("type:{}, value:\n{}".format(type(result), result))# 會話關閉 sess.close()# 當一個會話關閉后,不能再使用了,所以下面兩行代碼錯誤 # result2 = sess.run(c) # print(result2)- 調用 sess 的 run 方法來執行矩陣的乘法,得到c的結果值(所以將c作為參數傳遞進去)
- 不需要考慮圖中間的運算,在運行的時候只需要關注最終結果對應的對象以及所需要的輸入數據值
- 只需要傳遞進去所需要得到的結果對象,會自動的根據圖中的依賴關系觸發所有相關的OP操作的執行
- 如果op之間沒有依賴關系,tensorflow 底層會并行的執行op(有資源) --> 自動進行
- 如果傳遞的 fetches 是一個列表,那么返回值是一個 list 集合
- fetches:表示獲取那個op操作的結果值
c的結果:
g的結果:
補充:(可以使用with語句塊來開啟會話,自動關閉會話)
# 使用with語句塊,會在with語句塊執行完成后,自動的關閉session # allow_soft_placement:是否允許動態使用CPU和GPU,默認為False; # 當我們的安裝方式為GPU的時候,建議該參數設置為True,因為TensorFlow中的部分op只能在CPU上運行。 # log_device_placement: 是否打印日志,默認為False,不打印日志 with tf.Session(config=tf.ConfigProto(allow_soft_placement=True,?log_device_placement=True)) as sess2:print(sess2)# 獲取張量c的結果: 通過Session的run方法獲取print("sess2 run:{}".format(sess2.run(c)))# 獲取張量g的結果:通過張量對象的eval方法獲取,和Session的run方法一致print("c eval:{}".format(g.eval()))tf.Session 在構建會話的時候,如果不給定任何參數,那么構建出來的 Session 對應內部的 Graph,其實就是默認 Graph,不過我們可以通過參數給定具體對應的是那一個 Graph 以及當前 Session 對應的配合參數。
Session 的構造主要有三個參數,作用如下:
- target:給定連接的url,只有當分布式運行的時候需要給定;
- graph:給定當前Session對應的圖,默認為TensorFlow中的默認圖;
- config:給定當前Session的相關參數,詳見https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/prot
obuf/config.proto中的[ConfigProto]
通過Session的config參數可以對TensorFlow的應用的執行進行一些優化調整,主要涉及到的參數如下:
| 屬性 | 作用 |
| gpu_options | GPU相關參數,主要參數:per_process_gpu_memory_fraction和allow_growth |
| allow_soft_placement | 是否允許動態使用CPU和GPU,默認為False;當我們的安裝方式為GPU的時候, 建議該參數設置為True,因為TensorFlow中的部分op只能在CPU上運行 |
| log_device_placement | 是否打印日志,默認為False,不打印日志 |
| graph_options | Graph優化相關參數,一般不需要給定,默認即可,主要參數: optimizer_options(do_common_subexpression_elimination、do_constant_folding和opt_level) |
InteractiveSession會話(交互式會話)
使用交互式會話可以降低代碼的復雜度,使用 Tensor.eval() 或者 Operation.run() 來代替 Session.run() 方法,這樣可以避免一個變量來維持會話;
備注:Session也可以使用Tensor.eval()和Operation.run()獲取數據/執行操作(只要明確當前會話)。
import tensorflow as tf# 構建一個圖 a = tf.constant(4) b = tf.constant(3) c = tf.multiply(a, b)# 運行 with tf.Session():print(c.eval())# 進入交互式會話 sess = tf.InteractiveSession()# 定義變量和常量 x = tf.constant([1.0, 2.0]) a = tf.constant([2.0, 4.0])# 進行減操作 sub = tf.subtract(x, a)# 輸出結果 print(sub.eval()) print(sess.run(sub))張量(Tensor)
TensorFlow 使用 Tensor 數據結構來代表所有數據,計算圖中,操作間傳遞的數據都是 Tensor。Tensor 可以看作是一個 N 維的數組或者列表,一個 Tensor 主要由一個靜態數據類型和動態類型的維數(Rank、Shape)組成。Tensor 可以在圖中的節點之間流通。
變量(Variables)
變量(Variables)是維護圖執行過程中的狀態信息。在訓練模型過程中,可以通過變量來存儲和更新參數。變量包含張量(Tensor)存放于內存的緩存區。建模的時候變量必須被明確的初始化,模型訓練后變量必須被存儲到磁盤。這些變量的值可以在之后的模型訓練和分析中被加載。
在構建變量的時候,必須將一個 張量 或者 可以轉化為張量的 Python對象 作為初始值傳入構造函數Variable中。
import tensorflow as tf# 創建一個變量,初始化值為變量3.0 a = tf.Variable(3.0)# 創建一個常量 b = tf.constant(2.0) c = tf.add(a, b)# 啟動圖后,變量必須先進行初始化操作 # 增加一個初始化變量的op到圖中 init_op = tf.initialize_all_variables()# 啟動圖 with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:# 運行init_opsess.run(init_op)# 獲取值print("a = {}".format(sess.run(a)))print("c = {}".format(c.eval))變量依賴案例:
import tensorflow as tf# 創建一個變量 w1 = tf.Variable(tf.random_normal([10], stddev=0.5, dtype=tf.float32), name='w1') # 基于第一個變量創建第二個變量 a = tf.constant(2, dtype=tf.float32) w2 = tf.Variable(w1.initialized_value() * a, name='w2')# 進行全局初始化 init_op = tf.initialize_all_variables()# 啟動圖 with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:# 運行init_opsess.run(init_op)# 獲取值result = sess.run([w1, w2])print("w1 = {}\nw2 = {}".format(result[0], result[1]))取回(fetch)
為了取回操作的輸出內容,可以在使用 Session 對象的 run 方法調用執行圖的時候,傳入一些tensor,通過 run 方法就可以獲取這些 tensor 對應的結果值。
如果需要獲取多個tensor的值,那么盡量一次運行就獲取所有的結果值,而不是采用逐個獲取的方式。
with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:# 運行init_opsess.run(init_op)# 獲取值result = sess.run(fetches=[w1, w2])print("w1 = {}\nw2 = {}".format(result[0], result[1]))填充(feed)
在構建圖時使用 placeholder 類型的 API 臨時替代任意操作的張量(占位符),在調用 Session 對象的run() 方法去執行圖時,使用填充數據作為調用的參數,調用結束后,填充數據就消失了。
??feed 使用一個 tensor 值臨時替換一個操作的輸出結果,在獲取數據的時候必須給定對應的 feed 數據作為參數。feed 只有在調用它的方法內有效,方法結束,feed 就消失了。
??feed 可以使用 placeholder 類型的API創建占位符,常見API:tf.placeholder、tf.placeholder_with_default
import tensorflow as tf# 創建占位符,創建圖 m1 = tf.placeholder(tf.float32) m2 = tf.placeholder(tf.float32) m3 = tf.placeholder_with_default(4.0, shape=None) output = tf.multiply(m1, m2) ot1 = tf.add(m1, m3)# 運行圖 with tf.Session() as sess:print(sess.run(output, feed_dict={m1: 3, m2: 4}))print(output.eval(feed_dict={m1: 8, m2: 10}))print(sess.run(ot1, feed_dict={m1: 3, m3: 3}))print(sess.run(ot1, feed_dict={m1: 3}))變量更新(assign)
實例1:累加器
import tensorflow as tf# 1. 定義一個變量 x = tf.Variable(0, dtype=tf.int32, name='v_x')# 2. 變量的更新 assign_op = tf.assign(ref=x, value=x + 1)# 3. 變量初始化操作 x_init_op = tf.global_variables_initializer()# 3. 運行 with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:# 變量初始化sess.run(x_init_op)# 模擬迭代更新累加器for i in range(5):# 執行更新操作sess.run(assign_op)r_x = sess.run(x)print(r_x)實例二:動態的更新變量的維度數目
import tensorflow as tf# 1. 定義一個不定形狀的變量 x = tf.Variable(initial_value=[],dtype=tf.float32,trainable=False,validate_shape=False # 設置為True,表示在變量更新的時候,進行shape的檢查,默認為True )# 2. 變量更改 concat = tf.concat([x, [0.0, 0.0]], axis=0) assign_op = tf.assign(x, concat, validate_shape=False) # validate_shape 允許改變形狀# 3. 變量初始化操作 x_init_op = tf.global_variables_initializer()# 3. 運行 with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:# 變量初始化sess.run(x_init_op)# 模擬迭代更新累加器for i in range(5):sess.run(assign_op)r_x = sess.run(x)print(r_x)控制依賴
實例三:求階乘(控制依賴)
我們可以通過 Variable 和 assign 完成變量的定義和更新,但是如果在更新變量之前需要更新其它變量,那么會導致一個比較嚴重的問題:也就是需要多次調用 sess.run 方法來進行變量的更新。通過這種方式,代碼復雜程度上升,同時也沒有執行效率。
解決該問題的方案就是:控制依賴。
通過 TensorFlow 中提供的一組函數來處理不完全依賴的情況下的操作排序問題(即給定哪個操作先執行的問題), 通過 tf.control_dependencies API完成。
import tensorflow as tf# 1. 定義一個變量 sum = tf.Variable(1, dtype=tf.int32) # 2. 定義一個占位符 i = tf.placeholder(dtype=tf.int32)# 3. 更新操作 tmp_sum = sum * i # tmp_sum = tf.multiply(sum, i) assign_op = tf.assign(sum, tmp_sum) with tf.control_dependencies([assign_op]):# 如果需要執行這個代碼塊中的內容,必須先執行control_dependencies中給定的操作/tensorsum = tf.Print(sum, data=[sum, sum.read_value()], message='sum:')# 4. 變量初始化操作 x_init_op = tf.global_variables_initializer()# 5. 運行 with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:# 變量初始化sess.run(x_init_op)# 模擬迭代更新累加器for j in range(1, 6):# 執行更新操作# sess.run(assign_op, feed_dict={i: j})# 通過control_dependencies可以指定依賴關系,這樣的話,就不用管內部的更新操作了r = sess.run(sum, feed_dict={i: j})print("5!={}".format(r))設備(device)
設備 是指一塊可以用來運算并且擁有自己的地址空間的硬件,如 CPU 和 GPU 。Tensorflow 為了在執行操作的時候,充分利用計算資源,可以明確指定操作在哪個設備上執行。
一般情況下,不需要顯示指定使用 CPU 還是 GPU ,TensorFlow 會自動檢測。如果檢測到 GPU,TensorFlow會盡可能地利用第一個GPU來執行操作。
注意:如果機器上有超過一個可用的 GPU,那么除了第一個外其它GPU默認是不參與計算的。所以,在實際TensorFlow編程中,經常需要明確給定使用的 CPU 和 GPU。
- “/cpu:0”:表示使用機器CPU運算,cpu默認只有0個
- “/gpu:0”:表示使用第一個GPU運算,如果有的話
- “/gpu:1”:表示使用第二個GPU運算,以此類推
變量作用域(scope)
通過 tf.Variable 我們可以創建變量,但是當模型復雜的時候,需要構建大量的變量集,這樣會導致我們對于變量管理的復雜性,而且沒法共享變量(存在多個相似的變量)。針對這個問題,可以通過 TensorFlow 提供的變量作用域機制來解決,在構建一個圖的時候,就可以非常容易的使用共享命名過的變量。
Tensorflow中有兩個作用域:一個是 name_scope,另一個是 variable_scope
variable_scope
變量作用域機制在 TensorFlow 中主要通過兩部分組成:
- tf.get_variable:通過所給定的名字創建或者返回一個對應的變量
- tf.variable_scope:為通過創建的變量或者操作Operation指定命名空間
get_variable方法:
- tf.get_variable 方法在調用的時候,主要需要給定參數名稱name,形狀shape,數據類型dtype以及初始化方式initializer四個參數。
- 該API底層執行的時候,根據variable score的屬性reuse的值決定采用何種方式來獲取變量。
- 當reuse值為False的時候(不允許設置),作用域就是創建新變量設置的,此時要求對應的變量不存在,否則報錯;
- 當reuse值為True的時候,作用域就是為重用變量所設置的,此時要求對應的變量必須存在,否則報錯。
- 當reuse的值為tf.AUTO_REUSE的時候,表示如果變量存在就重用變量,如果變量不存在,就創建新變量返回。
- (備注:reuse一般設置在variable score對象上)
?
import tensorflow as tf# 方式一:不加作用域的 def my_func1(x):w1 = tf.Variable(tf.random_normal([1]))[0]b1 = tf.Variable(tf.random_normal([1]))[0]result1 = w1 * x + b1w2 = tf.Variable(tf.random_normal([1]))[0]b2 = tf.Variable(tf.random_normal([1]))[0]result2 = w2 * x + b2return result1, w1, b1, result2, w2, b2# 下面兩行代碼還是屬于圖的構建 x = tf.constant(3, dtype=tf.float32) r = my_func1(x)with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:# 初始化tf.global_variables_initializer().run()# 執行結果print(sess.run(r))# 方式二:加作用域 def my_func2(x):# initializer:初始化器w = tf.get_variable('weight', [1], initializer=tf.random_normal_initializer())[0]b = tf.get_variable('bias', [1], initializer=tf.random_normal_initializer())[0]result = w * x + breturn result, w, bdef func(x):with tf.variable_scope('op1', reuse=tf.AUTO_REUSE):r1 = my_func2(x)with tf.variable_scope('op2', reuse=tf.AUTO_REUSE):r2 = my_func2(x)return r1, r2# 下面兩行代碼還是屬于圖的構建 x1 = tf.constant(3, dtype=tf.float32, name='x1') x2 = tf.constant(4, dtype=tf.float32, name='x2') with tf.variable_scope('func1'): ?# 支持嵌套r1 = func(x1) with tf.variable_scope('func2'):r2 = func(x2)with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:# 初始化tf.global_variables_initializer().run()# 執行結果print(sess.run([r1, r2]))TF底層使用 '變量作用域/變量名稱:0'的方式標志變量(eg: func/op1/weight:0)
tf.get_variable 常用的 initializer 初始化器:
| 初始化器 | 描述 |
| tf.constant_initializer(value) | 初始化為給定的常數值value |
| tf.random_uniform_initializer(a, b) | 初始化為從a到b的均勻分布的隨機值 |
| tf.random_normal_initializer(mean, stddev)? | 初始化為均值為mean、方差為stddev的服從高斯分布的隨機值 |
| tf.orthogonal_initializer(gini=1.0)? | 初始化一個正交矩陣,gini參數作用是最終返回的矩陣是隨機矩陣乘以gini的結果 |
| tf.identity_initializer(gini=1.0)? | 初始化一個單位矩陣,gini參數作用是最終返回的矩陣是隨機矩陣乘以gini的結果 |
tf.variable_score
tf.variable_score方法的作用就是定義一個作用域,定義在 variable_score 作用域中的變量和操作,會將variable score 的名稱作為前綴添加到變量/操作名稱前,支持嵌套的作用域,添加前綴規則和文件目錄路徑的規則類似。
??tf.variable_score參數如果給定的是一個已經存在的作用域對象的時候,那么構建變量的時候表示直接跳過當前作用域前綴,直接成為一個完全不同與現在的作用域(直接創建給定作用域下的變量)。但是構建操作的時候,還是和嵌套的方式一樣,直接添加子作用域。
??tf.variable_score參數中,可以給定當前作用域中默認的初始化器initializer,并且子作用域會直接繼承父作用域的相關參數(是否重用、默認初始化器等)
import tensorflow as tfwith tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:with tf.variable_scope('foo', initializer=tf.constant_initializer(4.0)) as foo:v = tf.get_variable("v", [1])w = tf.get_variable("w", [1], initializer=tf.constant_initializer(3.0))with tf.variable_scope('bar'):l = tf.get_variable("l", [1])with tf.variable_scope(foo):h = tf.get_variable('h', [1])g = v + w + l + hwith tf.variable_scope('abc'):a = tf.get_variable('a', [1], initializer=tf.constant_initializer(5.0))b = a + gsess.run(tf.global_variables_initializer())print("{},{}".format(v.name, v.eval()))print("{},{}".format(w.name, w.eval()))print("{},{}".format(l.name, l.eval()))print("{},{}".format(h.name, h.eval()))print("{},{}".format(g.name, g.eval()))print("{},{}".format(a.name, a.eval()))print("{},{}".format(b.name, b.eval()))name_scope
name_score 的主要作用是為 op_name 前加前綴,variable_score 是為 get_variable 創建的變量的名字加前綴。
name_score 的主要作用就是:Tensorflow 中常常會有數以千計的節點,在可視化的過程中很難一下子展示出來,因此用 name_scope 為變量劃分范圍,在可視化中,這表示在計算圖中的一個層級。name_scope 會影響op_name,不會影響用get_variable()創建的變量,而會影響通過Variable()創建的變量。
簡單來講:使用 tf.Variable 創建的變量受 name_score 和 variable_score 的影響,會給變量添加前綴,但是使用 tf.get_variable 創建變量只受 variable_score 的影響。
import tensorflow as tfwith tf.Session() as sess:with tf.name_scope('name1'):with tf.variable_scope('variable1'):v = tf.Variable(1.0, name='v')w = tf.get_variable(name='w', shape=[1], initializer=tf.constant_initializer(2.0))h = v + wwith tf.variable_scope('variable2'):with tf.name_scope('name2'):v2 = tf.Variable(2.0, name='v2')w2 = tf.get_variable(name='w2', shape=[1], initializer=tf.constant_initializer(2.0))h2 = v2 + w2sess.run(tf.global_variables_initializer())print("{},{}".format(v.name, v.eval()))print("{},{}".format(w.name, w.eval()))print("{},{}".format(h.name, h.eval()))print("{},{}".format(v2.name, v2.eval()))print("{},{}".format(w2.name, w2.eval()))print("{},{}".format(h2.name, h2.eval()))可視化(Tensorboard)
TensorFlow提供了一套可視化工具:TensorBoard,在通過pip安裝 TensorFlow 的情況下,默認也會安裝TensorBoard。通過TensorBoard可以展示TensorFlow的圖像、繪制圖像生成的定量指標以及附加數據等信息。
TensorBoard 通過讀取 TensorFlow 的事件文件來運行,TensorFlow 的事件文件包括了在 TensorFlow運行中涉及到的主要數據,比如:scalar、image、audio、histogram和graph等。
通過 tf.summary 相關API,將數據添加 summary 中,然后在 Session 中執行這些操作得到一個序列化Summary protobuf 對象,然后使用 FileWriter 對象將匯總的序列數據寫入到磁盤,然后使用 tensorboard 命令進行圖標展示,默認訪問端口是:6006
TensorBoard中支持結構視圖和設備視圖。
import tensorflow as tfwith tf.variable_scope("foo"):with tf.device("/cpu:0"):x_init1 = tf.get_variable('init_x', [10], tf.float32, initializer=tf.random_normal_initializer())[0]x = tf.Variable(initial_value=x_init1, name='x')y = tf.placeholder(dtype=tf.float32, name='y')z = x + ywith tf.variable_scope("bar"):a = tf.constant(3.0) + 4.0# update xassign_op = tf.assign(x, x + 1)with tf.control_dependencies([assign_op]):with tf.device('/gpu:0'):out = x * ywith tf.device('/cpu:0'):with tf.variable_scope("bar"):a = tf.constant(3.0) + 4.0w = z * a# 開始記錄信息(需要展示的信息的輸出) tf.summary.scalar('scalar_init_x', x_init1) tf.summary.scalar(name='scalar_x', tensor=x) tf.summary.scalar('scalar_y', y) tf.summary.scalar('scalar_z', z) tf.summary.scalar('scala_w', w) tf.summary.scalar('scala_out', out)with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:# merge all summarymerged_summary = tf.summary.merge_all()# 得到輸出到文件的對象writer = tf.summary.FileWriter('./result', sess.graph)# 初始化sess.run(tf.global_variables_initializer())for i in range(1, 5):summary, r_out, r_x, r_w = sess.run([merged_summary, out, x, w], feed_dict={y: i})writer.add_summary(summary, i)print("{},{},{}".format(r_out, r_x, r_w))# 關閉操作writer.close()API
| API | 描述 |
| tf.summary.scalar | 添加一個標量 |
| tf.summary.audio | 添加一個音頻變量 |
| tf.summary.image | 添加一個圖片變量 |
| tf.summary.histogram | 添加一個直方圖變量 |
| tf.summary.text | 添加一個字符串類型的變量(一般很少用) |
查看可視化結果步驟:
- 打開cmd命令行輸入:tensorboard --helpfull 可以查看相關幫助命名
- 輸入:tensorboard --logdir F:\All_worlspace\Pycharm_workspace\DeepLearning\Tensorflow-basic\result 這里的路徑是你保存輸出文件對象的路徑
- 在瀏覽器中輸入上圖紅色框內的
- 雙擊圖中的foo或bar會打開,如下圖
模型保存、提取(Saver)
TensorFlow 使用 tf.train.Saver 類實現模型的保存和提取。
Saver對象的saver方法將TensorFlow模型保存到指定路徑中。
通過Saver對象的restore方法可以加載模型,并通過保存好的模型變量相關值重新加載完全加載進來。
如果不希望重復定義計算圖上的運算,可以直接加載已經持久化的圖,通過 tf.train.import_meta_graph 方法直接加載
備注:在加載的時候,可以在Saver對象構建的時候,明確給定變量名之間的映射關系
import tensorflow as tf# # 模型保存 # v1 = tf.Variable(tf.constant(3.0), name='v1') # v2 = tf.Variable(tf.constant(4.0), name='v2') # result = v1 + v2 # # saver = tf.train.Saver() # with tf.Session() as sess: # ? ? sess.run(tf.global_variables_initializer()) # ? ? sess.run(result) # ? ? # 模型保存到model文件夾下,文件前綴為:model.ckpt # ? ? saver.save(sess, './model/model.ckpt')# 模型的提取(完整提取:需要完整恢復保存之前的數據格式) v1 = tf.Variable(tf.constant(1.0), name='v1') v2 = tf.Variable(tf.constant(4.0), name='v2') result = v1 + v2saver = tf.train.Saver() with tf.Session() as sess:# 會從對應的文件夾中加載變量、圖等相關信息saver.restore(sess, './model/model.ckpt')print(sess.run([result]))# 直接加載圖,不需要定義變量了 saver = tf.train.import_meta_graph('./model/model.ckpt.meta')with tf.Session() as sess:saver.restore(sess, './model/model.ckpt')print(sess.run(tf.get_default_graph().get_tensor_by_name("add:0")))# 模型的提取(給定映射關系) a = tf.Variable(tf.constant(1.0), name='a') b = tf.Variable(tf.constant(2.0), name='b') result = a + bsaver = tf.train.Saver({"v1": a, "v2": b}) with tf.Session() as sess:# 會從對應的文件夾中加載變量、圖等相關信息saver.restore(sess, './model/model.ckpt')print(sess.run([result]))總結
至此,關于Tensorflow的基礎入門大概就這么多,此外還會涉及到線程和隊列、數據讀取、分布式訓練等,可以在以后深入學習,理解。
總結
以上是生活随笔為你收集整理的TensorFlow 基本操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JS常用正则表达式大全
- 下一篇: 基于三维冲击波的变分理论--交通运输工程