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