天天看點

TensorFlow 基礎知識1 張量2 TensorFlow的Operation3 Graph對象4 Session5 利用占位節點添加輸入6 Variable對象7 通過名稱作用域組織資料流圖可視化

參考資料:

TensorFlow 采用資料流圖進行數值計算。節點代表計算圖中的數學操作,計算圖的邊表示多元數組,即張量。

在 TensorFlow 官網上将其定義為基于資料流圖的數值計算庫,TensorFlow 還提供了一個可使得使用者用數學方法從零開始定義模型的函數和類的廣泛套件。這使得具有一定技術背景的使用者可迅速而直覺地建立自定義、具有較高靈活性的模型。

TensorFlow 的計算模型是有向圖,其中的每個節點(通常以圓圈或方框表示)代表了一些函數或計算,而邊(通常以箭頭或線段表示)代表了數值、矩陣、張量。TensorFlow 能夠自動計算任意節點關于其他對第一個節點的輸出産生影響的任意節點的導數(即 Operation),還可以通過計算的分解,将計算分布在多個 CPU、GPU 以及其他計算裝置上(隻需要将完整的、較大的資料流圖分解為一些較小的計算圖,并借由一定的邏輯對不同裝置間的共享資訊進行排程來讓每台計算裝置負責一個獨立的計算子圖)。

定義資料流圖

TensorFlow的核心工作模式:

1. 定義資料流圖

2. 運作資料流圖(在資料上)

import tensorflow as tf             
# 在“input”節點上輸入資料
a = tf.constant(5, name= 'input_a')
b = tf.constant(3, name= 'input_b')

# 定義運算節點“Operation”(簡稱:Op)
c = tf.multiply(a, b, name= 'mul_c')
d = tf.add(a, b, name= 'add_d')
e = tf.add(c, d, name= 'add_e')

# 運作資料流圖
with tf.Session() as sess:
    s = sess.run(e)
    print(s)           
23           

建立

summary.FileWriter

對象,并指派給writer

writer = tf.summary.FileWriter('./my_graph', sess.graph)           
writer.close()
sess.close()           
a = tf.constant([5, 3], name= 'input_a')
b = tf.reduce_prod(a, name= 'prod_b')   # 所有元素的乘積
c = tf.reduce_sum(a, name= 'sum_c')    # 所有元素的和
d = tf.add(c, d, name= 'add_d')           
with tf.Session() as sess:
    print(sess.run([a, b, c, d]))           
[array([5, 3]), 15, 8, 16]           

1 張量

1.1 Python原生類型

TensorFlow可接收Python數值、布爾值、字元串或由它們構成的清單。

單個數值将會被轉化為0階張量(或标量),數值清單将被轉化為2階張量(矩陣),以此類推。

t0 = 50             # 标量
t1 = [b'apple', b'peach', b'grape']  # 向量
t2 = [[1, 3], [3, 5]]    # 矩陣           

可将張量視為一種以結構化格式儲存任意資料的方式。

TensorFlow資料類型

資料類型(dtype) 描述

tf.float32

32位浮點型

tf.float64

64位浮點型

tf.int8

8位由符号整數

tf.int16

16位由符号整數

tf.int32

32位由符号整數

tf.int64

64位由符号整數

tf.uint8

8位由無符号整數

tf.string

字元串(作為非Unicode編碼的位元組數組)

tf.bool

布爾型

tf.complex64

複數,實部和 虛部分别為32位浮點型

tf.qint8

8位有符号整數(用于量化)

tf.qint328

32位有符号整數(用于量化)

tf.quint8

8位有無符号整數(用于量化)

tf.quint32

32位無符号整數(用于量化)

1.2 Numpy

TensorFlow的資料類型是基于NumPy的資料類型:

import numpy as np           
np.int64 == tf.int64           
True           

任何一個NumPy數組均可傳遞給TensorFlow Op:

字元串資料類型

對于數值類型和布爾類型TensorFlow和NumPy dtype屬性是完全一緻的。然而,在NumPy中并無與tf.string精确對應的類型。即TensorFlow可以從NumPy中完美地導入字元串數組,隻是不要在NumPy中顯式指定dtype。

在運作資料流圖之前之後,都可以利用NumPy庫的功能,因為從Session.run方法傳回的張量均為NumPy數組。

t1 = np.array(50, dtype= np.int64)           
# 在NumPy中使用字元串時,不要顯式指定dtype屬性
t2 = np.array([b'apple', b'peach', b'grape'])           
t3 = np.array([[True, False, False],[False, False, True], [False, True, True]], dtype = np.bool)           
t4 = np.array([[[1]]], dtype= np.float32)           

雖然TensorFlow是為了解NumPy原生資料類型而設計的,但反之不然。請不要嘗試用tf.int32去初始化一個NumPy數組。

a = np.array(3, np.int) # 不是np.int32
a.dtype             
dtype('int32')           
a = np.array(3, np.float) 
a.dtype             
dtype('float64')           
a = np.array(3, np.float64) 
a.dtype             
dtype('float64')           
a = np.array(3, np.float32) 
a.dtype             
dtype('float32')           

手工指定Tensor對象時,使用NumPy是推薦的方式。

  1. 深度學習架構太抽象?其實不外乎這五大核心元件
  2. 常見問題

1.3 張量的形狀

“形狀”是TensorFlow的專有術語,它同時刻畫了張量的維(階)數以及每一維的長度。形式可以是清單或元組。

t1.shape   # 标量           
()           
t2.shape   # 向量           
(3,)           
t3.shape  # 矩陣           
(3, 3)           
t4.shape  # 3維數組(張量)           
(1, 1, 1)           

也可以将None作為某一維的長度,使得該張量具有可變長度。

此外,将形狀指定為None,将通知TensorFlow允許一個張量為任意形狀。

如果需要在資料流圖的中間擷取某個張量的形狀,可使用tf.shape Op。它的輸入為希望擷取形狀的Tensor對象,輸出為一個int32類型的向量。

shape = tf.shape(t3, name= 't3_shape')
shape           
<tf.Tensor 't3_shape:0' shape=(2,) dtype=int32>           
with tf.Session() as sess:
    print(sess.run(shape))           
[3 3]           

2 TensorFlow的Operation

在TensorFlow中,資料流圖本質上是一組連結在一起的函數,每個函數都會将其輸出傳遞給0個、1個或多個位于這個級聯鍊上的其他函數。按照這種方式,使用者可利用一些很小的、為人們所充分了解的數學函數構造資料的複雜變換。

資料流圖的兩個基本構件:節點和邊。

2.1 節點(node)

節點通常以圓圈、橢圓和方框表示,代表了對資料所做的運算和某種操作。

“input”節點的作用僅僅是傳遞Tensor的輸入值。

sess = tf.InteractiveSession()           
# 初始化一些計算需要的張量
a = np.array([2, 3], dtype= np.int)  # input_Op(節點)
a.dtype           
dtype('int32')           
b = np.array([4, 5], dtype= np.int) # input_Op
# 利用tf.add() 初始化一個"add" Op
# 變量c為指向該Op的Tensor對象的句柄
c = tf.add(a, b)   # add Op
s = c.eval()
s           
array([6, 8])           
type(c)   # c是Tensor對象           
tensorflow.python.framework.ops.Tensor           
type(s) # s是數組,即張量的輸出值           
numpy.ndarray           

TensorFlow中,資料流圖中的每個節點都被稱為一個“Operation”(簡記:Op)。各Op可接收0個或多個Tensor對象作為輸入,并輸出0個或多個Tensor對象。要建立一個Op,可調用與其關聯的Python構造方法。比如:

# `tf.constant`建立了一個常量Op,可接收單個張量值,然後将同樣的值輸出給其直接連接配接的節點。
## 自動将标量值轉化為了Tensor對象。
r = tf.constant(5, name= 'input_a')
r           
<tf.Tensor 'input_a_4:0' shape=() dtype=int32>           
type(r.eval())           
numpy.int32           
type(r)           
tensorflow.python.framework.ops.Tensor           

2.2 邊(edge)

edge

對應于向Operation傳入和從Operation傳出的實際數值(可以視為Tensor),通常以箭頭表示。

可從概念上将邊視為不同的Operation之間的連接配接,因為它們将資訊從一個節點傳輸到另一個節點。

運算符重載

運算符 相關TensorFlow運算

-x

tf.negative()

傳回x中的每個元素的相反數

~x

tf.logical_not

傳回x中的每個元素的邏輯非。隻适用于dtype為tf.bool的Tensor對象

abs(x)

tf.abs(x)

傳回x中的每個元素的絕對值

x + y

tf.add()

将下x, y逐元素相加

x - y

tf.subtract

将下x, y逐元素相減

x * y

tf.multiply

将下x, y逐元素相乘

x / y

(Python 2.x)

tf.div

給定整數張量時,執行逐元素的整數除法;給定浮點數型張量,将執行逐元素的浮點數除法

x / y

(Python 3.x)

tf.truediv

逐元素的浮點數除法(包括分子、分母為整數的情形)

x // y

tf.floordiv

逐元素的向下取整除法,部傳回餘數

x % y

tf.mod()

逐元素取模

x ** y

tf.pow()

逐一計算x中的每一個元素為底數,y中相應的元素為指數時的幂

x < y

tf.less

逐元素地計算\(x < y\)的真值表

x <= y

tf.less_equal()

逐元素地計算\(x <= y\)的真值表

x > y

tf.greater()

逐元素地計算\(x > y\) 的真值表

x >= y

tf.greater_equal()

逐元素地計算\(x >= y\)的真值表

x & y

tf.logical_and()

逐元素地計算\(x \& y\)的真值表, 每個元素的dtype屬性必須為

tf.bool

x

\(\mid\)

y

tf.logical_or()

逐元素地計算\(x \mid y\)的真值表, 每個元素的dtype屬性必須為

tf.bool

x ^ y

tf.logical_xor()

逐元素地計算

x ^ y

的真值表, 每個元素的dtype屬性必須為

tf.bool

tf.equal()

tf.not_equal

用于檢查兩個張量是否相等,傳回布爾值張量,需要使用

tf.cast

轉化為 \(1\) 和 \(0\)。

sess = tf.InteractiveSession()           
tf.global_variables_initializer().run()           
-c.eval()           
array([-6, -8])           
tf.negative(c).eval()           
array([-6, -8])           
tf.div(34, 5).eval()           
6           
a = np.array([1, 3, 5, 4])
b = np.array([3, 4, 2, 3])           
a ** b           
array([ 1, 81, 25, 64], dtype=int32)           
np.power(a, b)           
array([ 1, 81, 25, 64], dtype=int32)           
tf.pow(a, b).eval()           
array([ 1, 81, 25, 64])           
a == b           
array([False, False, False, False], dtype=bool)           
np.equal(a, b)           
array([False, False, False, False], dtype=bool)           
tf.equal(a, b).eval()           
array([False, False, False, False], dtype=bool)           
c = tf.constant(a)
d = tf.constant(b)
c == d           
False           
tf.equal(c, d).eval()           
array([False, False, False, False], dtype=bool)           
import numpy as np
a = np.array([1.44, 3.33, 5.0, 4])
b = np.array([-3, 4, -2, 3])
tf.ceil(a).eval()  # 向上取整           
array([ 2.,  4.,  5.,  4.])           
tf.floor(a).eval()  # 向下取整           
array([ 1.,  3.,  5.,  4.])           
tf.round(a).eval()  # 4舍5入           
array([ 1.,  3.,  5.,  4.])           
tf.abs(b).eval() # 絕對值           
array([3, 4, 2, 3])           
tf.cos(a).eval()           
array([ 0.13042371, -0.98230378,  0.28366219, -0.65364362])           
tf.exp(a).eval()           
array([   4.22069582,   27.9383417 ,  148.4131591 ,   54.59815003])           
tf.maximum(a, b).eval()   # 傳回兩個張量中最大的值           
array([ 3.,  4.,  5.,  4.])           
tf.minimum(a, b).eval()            
array([ 1.44,  3.33,  2.  ,  3.  ])           
tf.rsqrt(a).eval() # 傳回平方根的倒數           
array([ 0.83333333,  0.54799662,  0.4472136 ,  0.5       ])           
tf.sqrt(a).eval() # 傳回平方根           
array([ 1.2       ,  1.82482876,  2.23606798,  2.        ])           
c = tf.constant([-2, 4, 5, 0, -3])
tf.sign(c).eval()  # 根據輸入的張量的符号,符号-1,1, 0           
array([-1,  1,  1,  0, -1])           
tf.square(c).eval()  # 張量的平方           
array([ 4, 16, 25,  0,  9])           
tf.digamma(a).eval()  # 浦西函數(Psi函數),lgamma() 函數的導數           
array([-0.02114267,  1.04537223,  1.50611767,  1.25611767])           
tf.erf(a).eval() # 高斯誤差函數           
array([ 0.95829657,  0.99999751,  1.        ,  0.99999998])           
tf.erfc(a).eval() # 互補誤差函數           
array([  4.17034304e-02,   2.48530987e-06,   1.53745979e-12,
         1.54172579e-08])           
tf.igamma(a, b).eval() # 下不完全伽馬函數           
array([ 0.89723547,  0.70058193,  0.05265302,  0.35276811])           
tf.igammac(a, b).eval() # 上不完全伽馬函數           
array([ 0.10276453,  0.29941807,  0.94734698,  0.64723189])           
tf.lbeta(a).eval()   # 貝塔函數絕對值的自然對數           
-16.088605561849441           
tf.lgamma(a).eval()   # 伽馬函數絕對值的自然對數           
array([-0.12125837,  1.01830177,  3.17805383,  1.79175947])           
tf.squared_difference(a, b).eval() # 內插補點的平方           
array([ 2.4336,  0.4489,  9.    ,  1.    ])           

2.3 節點的依賴關系

我們可以将整個節點序列抽象為擁有輸入和輸出的離散構件。這樣使得級聯在一起的若幹運算組進行可視化更加容易,而無需關注每個部件的具體細節。

對于任意節點A,若其輸出對于某個後繼節點B的計算是必需的,則稱節點A為節點B的依賴節點。

若某個節點A和節點B彼此不需要來自對方的任何資訊,則稱兩者是獨立的。

任何節點都可以将其輸出傳遞給資料流圖中的任何後繼節點,而無論這兩者之間發生了多少計算。

在TensorFlow中,真正的循環依賴關系是無法表示的,在實際使用中,完全可以通過對資料流圖進行有限次的複制,然後将它們并排放置,并将代表相鄰疊代輪次的副本的輸出與輸入串接。(此過程稱為資料流圖的“展開(unrolling)”)這樣等價于将之前的資料流圖周遊多次。

3 Graph對象

建立一個Graph對象的方法十分簡單:

# 建立一個新的資料流圖
g = tf.Graph()           

Graph對象初始化完成後,便可利用

tf.Graph.as_default()

方法通路其上下文管理器,為其添加Op。結合with語句,可利用上下文管理器通知TensorFlow我們需要添加到某個特定的Graphdx中:

with g.as_default():
    # 建立一些Op,它們将會被添加到Graph對象g中
    a = tf.multiply(2, 3)
    ...           

當TensorFlow庫被加載時,它會自動建立一個Graph對象,并将其作為預設的資料流圖。是以,在

tf.Graph.as_default()

上下文管理器之外的任何Op、Tensor對象都會自動放置在預設的資料流圖中:

# 放置在預設資料流圖中
in_default_graph = tf.add(1, 2)

# 放置在預設資料流圖 g 中
with g.as_default():
    # 建立一些Op,它們将會被添加到Graph對象g中
    in_graph_g = tf.multiply(2, 3)           
# 由于不在with語句塊中,下面的Op将放置在預設的資料流圖中
also_in_default_graph = tf.subtract(5, 1)           

如果希望得到預設資料流圖的句柄,可使用

tf.get_default_graph()

函數:

default_graph = tf.get_default_graph()
default_graph           
<tensorflow.python.framework.ops.Graph at 0x251a066ca20>           
  1. 如若需要定義多個互相之間不存在依賴關系的模型,則建立多個Graph對象十分有用。
  2. 當需要在單個檔案中定義多個資料流圖時,最佳的實踐是不使用預設資料流圖,或為其立即配置設定句柄。這樣可以保證各個節點按照一緻的方式添加到每個資料流圖中。

3.1 正确的實踐——建立新的資料流圖,将預設的資料流圖忽略

import tensorflow as tf

g1 = tf.Graph()
g2 = tf.Graph()

with g1.as_default():
    # 定義g1的Op、張量等
    ...
    
with g2.as_default():
    # 定義g2的Op、張量等
    ...           

3.2 正确的實踐——擷取預設資料流圖的句柄

import tensorflow as tf

g1 = tf.get_default_graph()
g2 = tf.Graph()

with g1.as_default():
    # 定義g1的Op、張量等
    ...
    
with g2.as_default():
    # 定義g2的Op、張量等
    ...           

3.3 錯誤的實踐——将預設的資料流圖和使用者建立的資料流圖混合使用

import tensorflow as tf


g2 = tf.Graph()

# 定義預設的資料流圖的Op、張量等
...
    
with g2.as_default():
    # 定義g2的Op、張量等
    ...           

此外,從其他TensorFlow腳本中加載之前定義過的模型,并利用

Graph.as_graph_def()

tf.import_graph_def()

函數将其賦給Graph對象也是可行的。這樣使用者可在同一個Python檔案中計算和使用若幹獨立的模型輸出。

4 Session

Session

類負責資料流圖的執行。

4.1 構造方法

tf.Session()

接收3個可選參數:

  1. target

    指定了所要使用的執行引擎。
    • 對于大多數應用,該參數取為預設的空字元串。
    • 在分布式設定中該參數用于連接配接不同的

      tf.train.Server

      執行個體。
  2. graph

    指定了将要加載的Graph對象,其預設值為None,表示将使用目前預設資料流圖。當使用多個資料流圖時,最好的傳入方式是顯式傳入你希望運作的Graph對象(而非在一個with語句塊内建立Session對象)。
  3. config

    參數允許使用者指定配置Session對象所需選項,如限制CPU或GPU的使用數目,為資料流圖設定優化參數和日志選項等。

在典型的TensorFlow程式中,建立Session對象時無需改變任何預設構造參數。

import tensorflow as tf

# 建立Op、Tensor對象等(使用預設資料流圖)
a = tf.add(2, 5)
b = tf.multiply(a, 3)

# 利用預設資料流圖啟動一個Session對象
sess = tf.Session()
# 或者傳入參數
sess = tf.Session(graph = tf.get_default_graph())           

一旦建立完Session,便可利用其主要方法

run()

eval()

來計算所期望的Tensor對象的輸出:

sess.run(b)           
21           
b.eval()           
21           

4.2

Session.run()

run()接收一個參數

fetchs

,以及其他三個可選參數:

feed_dict

options

run_metadata

fetchs

參數接收任意的資料流圖元素(Op、Tensor對象),後者指定了使用者希望執行的對象。

  • 若請求對象為Tensor,則

    run()

    的輸出為一個NumPy數組;
  • 若請求對象為一個Op,則輸出為None。
  • 若請求對象為一個資料流圖元素的清單,則輸出一個與所請求的元素對應的值的清單。
sess.run([a, b])           
[7, 21]           

feed_dict

參數用于覆寫資料流圖中的Tensor對象值,它需要Python字典對象作為輸入。字典中的“鍵”為指向應當覆寫的Tensor對象的句柄,而字典的“值”、字元串、清單或NumPy數組。

這些“值”的類型必須與Tensor的“鍵”相同,或能轉化為相同的類型。

# 定義一個字典,将a的值替換為15
replace_dict = {a: 15}           
# 将replace_dict指派給feed_dict
sess.run(b, feed_dict= replace_dict)           
45           
# 關閉資料流圖,釋放資源
sess.close()           

5 利用占位節點添加輸入

占位符的行為和Tensor對象一緻,但在建立時無需為它們指定具體的數值。它的作用是為運作時即将到來的某個Tensor對象預留位置,是以實際上變成了“輸入”節點。

利用

tf.placeholder

Op可建立占位符。

  • dtype

    (是必須指定的)指定了該占位符的值的資料類型。
  • shape

    (可選)指定了傳入的Tensor對象的形狀。預設值為

    None

    ,表示可以接收任意形狀的Tensor對象。
  • 與任何Op一樣,也可以在

    tf.placeholder

    中指定一個

    name

    辨別符。
  • 為了給占位符傳入一個實際的值,需要使用

    Session.run()

    feed_dict

    參數。将指向占位符輸出的句柄作為字典的“鍵”,而希望傳入的Tensor對象作為字典的“值”:
# 建立一個長度為2,資料類型為int32的占位向量
a = tf.placeholder(tf.int32, shape= [2], name= 'my_input')

# 将該占位符視為其他任意Tensor對象,加以使用
b = tf.reduce_prod(a, name= 'prob_a')
c = tf.reduce_sum(a, name= 'sum_a')

# 完成資料流圖的定義
d = tf.add(b, c, name= 'add_d')           
sess = tf.Session()           
# 建立一個将傳給feed_dict參數的字典
# “鍵”:`a` 指向占位符輸出Tensor對象的句柄
input_dict = {a: np.array([5, 3], dtype= np.int)}           
# 計算d, 将input_dict的“值”傳給a
sess.run(d, feed_dict= input_dict)           
23           
sess.run(a, feed_dict= input_dict)           
array([5, 3])           

6 Variable對象

Tensor對象和Op對象都是不可變的(immutable),Variable對象是可變的。

6.1 建立Variable對象

tf.Variable()

# 為Variable對象傳入初始值
my_var = tf.Variable(3, name= 'my_variable')           

Variable對象可用于任何可能會使用Tensor對象的TensorFlow函數或Op中,其目前值将傳給使用它的Op:

add = tf.add(5, my_var)
mul = tf.multiply(8, my_var)           

6.2 Variable對象初始化

注意:

tf.truncated_normal()

函數不會建立任何偏離均值超過2倍标準差的值,進而可以防止有一個或兩個元素于該張量中的其他元素顯著不同的情況出現:

# 該Tensor對象不會傳回任何小于0.3或大于7.0的值
trunc = tf.truncated_normal([2, 2], mean= 5.0, stddev= 1.0)           

可像手工初始化張量那樣将Op作為Variable對象的初值傳入:

random_var = tf.Variable(tf.truncated_normal([2, 2])) # 預設均值為0, 标準差為 1           

Variable對象與大多數其他TensorFlow對象在Graph中存在的方式都比較類似,但是它們的狀态實際上是由Session對象管理的。是以,為使用Variable對象,必須在一個Session對象内對Variable對象進行初始化(

tf.global_variables_initializer().run()

)這樣會使Session對象開始追蹤Variable對象的值的變化。

tf.variables_initializer()

對部分Variable對象進行初始化。

6.3 Variable對象的修改

可使用

Variable.assign()

(是一個Op,要使其生效必須在一個Session對象中運作)方法修改Variable對象:該方法的作用是為Variable對象賦予新值。

# 建立初始值為 1 的 Variable對象
my_var = tf.Variable(1)           
# 建立一個Op,使其在每次運作時都将該Variable對象乘以 2
my_var_times_two = my_var.assign(my_var * 2)           
# 初始化Op
init_op = tf.global_variables_initializer()           
# 啟動一個會話
sess = tf.Session()           
# 初始化Variable對象
sess.run(init_op)           
# 将Variable對象乘以 2,并将其傳回
sess.run(my_var_times_two)           
2           
# 再次相乘
sess.run(my_var_times_two)           
4           
# 再次相乘
sess.run(my_var_times_two)           
8           

對于Variable對象自增、自減:

Variable.assign_add()

Variable.assign_sub()

# 自增 1
sess.run(my_var.assign_add(1))           
9           
# 自減 1
sess.run(my_var.assign_sub(1))           
8           

由于不同的Session對象會各自獨立地維護Variable對象的值,是以每個Session對象都擁有自己的、在Graph對象中定義的Variable對象的目前值:

# 建立一些Op
my_var = tf.Variable(0)
init_op = tf.global_variables_initializer()           
# 啟動多個Session對象
sess1 = tf.Session()
sess2 = tf.Session()           
# 在sess1内對Variable對象進行初始化,以及在同一Session對象中對my_var的值自增
sess1.run(init_op)
sess1.run(my_var.assign_add(5))           
5           
# 在sess2内對Variable對象進行初始化,以及在同一Session對象中對my_var的值自增
sess2.run(init_op)
sess2.run(my_var.assign_add(2))           
2           
# 能夠在不同的Session對象中獨立地對Variable對象的值實施自增運算
sess1.run(my_var.assign_add(5))           
10           
sess2.run(my_var.assign_add(2))           
4           

如果希望将所有的Variable對象的值重置為初始值,則隻需再次調用

tf.global_variables_initializer()

,如若隻希望對部分Variable對象重新初始化,可調用

tf.variables_initializer()

# Variable對象的值重置為初始值
sess1.run(init_op)
sess1.run(my_var)           
my_var = tf.Variable(2)
my_var1 = tf.Variable(5)
my_var_times_two = my_var.assign(my_var * 2)
my_var1_times_two = my_var.assign(my_var1 * 2)
sess = tf.Session()
# 部分Variable對象的值重置為初始值
sess.run(tf.variables_initializer([my_var, my_var1]))
print(sess.run(my_var_times_two))
print(sess.run(my_var1_times_two))           
4
10           

6.4 trainable 參數

Optimizer

為自動訓練機器學習模型的類,它們可以自動修改Variable對象的值,而無需顯式地做出請求。

如果要求Graph對象中的一些Variable對象隻可手工修改,而不允許使用

Optimizer

類,可在建立這些Variable對象時将其參數

trainable

設定為

False

not_trainable = tf.Variable(0, trainable= False)           

對于疊代計數器或其他任何不涉及機器學習模型計算的Variable對象,通常都需要将Variable對象的參數trainable設定為False。

7 通過名稱作用域組織資料流圖

名稱作用域(name scope)非常易于使用,且在用TensorBoard對Graph對象可視化時極有價值。

本質上,名稱作用域允許将Op劃分到一些較大的、有名稱的語句塊中。當以後使用TensorBoard加載資料流圖時,每個名稱作用域都将對其自己的Op進行封裝,進而獲得更好的可視化效果。

名稱作用域的基本用法是将Op添加到語句塊

with tf.name_scope(<name>)

中。

with tf.name_scope('Scope_A'):
    a = tf.add(1, 2, name= 'A_add')
    b = tf.multiply(a, 3, name= 'A_mul')
    
with tf.name_scope('Scope_B'):
    c = tf.add(4, 5, name= 'B_add')
    d = tf.multiply(c, 6, name= 'B_mul')
    
e = tf.add(b, d, name= 'output')           
# 打開一個summary.FileWriter對象,并将Graph對象寫入磁盤
writer = tf.summary.FileWriter('./name_scope_1',
                              graph= tf.get_default_graph())
writer.close()           

可視化

由于

summary.FileWriter

對象會将資料流圖立即導出,可在運作完上述代碼便啟動TensorBoard。導航到運作上述腳本的路徑,并啟動TensorBoard:

!tensorboard --logdir= './name_scope_1'           
Traceback (most recent call last):
  File "c:\programdata\anaconda3\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "c:\programdata\anaconda3\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\ProgramData\Anaconda3\Scripts\tensorboard.exe\__main__.py", line 9, in <module>
  File "c:\programdata\anaconda3\lib\site-packages\tensorboard\main.py", line 36, in run_main
    tf.app.run(main)
  File "c:\programdata\anaconda3\lib\site-packages\tensorflow\python\platform\app.py", line 48, in run
    _sys.exit(main(_sys.argv[:1] + flags_passthrough))
  File "c:\programdata\anaconda3\lib\site-packages\tensorboard\main.py", line 45, in main
    default.get_assets_zip_provider())
  File "c:\programdata\anaconda3\lib\site-packages\tensorboard\program.py", line 161, in main
    tb = create_tb_app(plugins, assets_zip_provider)
  File "c:\programdata\anaconda3\lib\site-packages\tensorboard\program.py", line 185, in create_tb_app
    raise ValueError('A logdir must be specified when db is not specified. '
ValueError: A logdir must be specified when db is not specified. Run `tensorboard --help` for details and examples.           
!tensorboard --help           
usage: tensorboard.exe [-h]
                       [--debugger_data_server_grpc_port DEBUGGER_DATA_SERVER_GRPC_PORT]
                       [--logdir LOGDIR] [--host HOST] [--port PORT]
                       [--purge_orphaned_data [PURGE_ORPHANED_DATA]]
                       [--nopurge_orphaned_data]
                       [--reload_interval RELOAD_INTERVAL] [--db DB]
                       [--inspect [INSPECT]] [--noinspect] [--tag TAG]
                       [--event_file EVENT_FILE] [--path_prefix PATH_PREFIX]

optional arguments:
  -h, --help            show this help message and exit
  --debugger_data_server_grpc_port DEBUGGER_DATA_SERVER_GRPC_PORT
                        The port at which the debugger data server (to be
                        started by the debugger plugin) should receive
                        debugging data via gRPC from one or more debugger-
                        enabled TensorFlow runtimes. No debugger plugin or
                        debugger data server will be started if this flag is
                        not provided.
  --logdir LOGDIR       logdir specifies the directory where TensorBoard will
                        look to find TensorFlow event files that it can
                        display. TensorBoard will recursively walk the
                        directory structure rooted at logdir, looking for
                        .*tfevents.* files. You may also pass a comma
                        separated list of log directories, and TensorBoard
                        will watch each directory. You can also assign names
                        to individual log directories by putting a colon
                        between the name and the path, as in tensorboard
                        --logdir name1:/path/to/logs/1,name2:/path/to/logs/2
  --host HOST           What host to listen to. Defaults to serving on all
                        interfaces, set to 127.0.0.1 (localhost) to disable
                        remote access (also quiets security warnings).
  --port PORT           What port to serve TensorBoard on.
  --purge_orphaned_data [PURGE_ORPHANED_DATA]
                        Whether to purge data that may have been orphaned due
                        to TensorBoard restarts. Disabling purge_orphaned_data
                        can be used to debug data disappearance.
  --nopurge_orphaned_data
  --reload_interval RELOAD_INTERVAL
                        How often the backend should load more data.
  --db DB               [Experimental] Sets SQL database URI. This mode causes
                        TensorBoard to persist experiments to a SQL database.
                        The following databases are supported: - sqlite: Use
                        SQLite built in to Python. URI must specify the path
                        of the database file, which will be created if it
                        doesn't exist. For example: --db
                        sqlite3:~/.tensorboard.db Warning: This feature is a
                        work in progress and only has limited support.
  --inspect [INSPECT]   Use this flag to print out a digest of your event
                        files to the command line, when no data is shown on
                        TensorBoard or the data shown looks weird. Example
                        usages: tensorboard --inspect --event_file
                        myevents.out tensorboard --inspect --event_file
                        myevents.out --tag loss tensorboard --inspect --logdir
                        mylogdir tensorboard --inspect --logdir mylogdir --tag
                        loss See
                        tensorflow/python/summary/event_file_inspector.py for
                        more info and detailed usage.
  --noinspect
  --tag TAG             The particular tag to query for. Only used if
                        --inspect is present
  --event_file EVENT_FILE
                        The particular event file to query for. Only used if
                        --inspect is present and --logdir is not specified.
  --path_prefix PATH_PREFIX
                        An optional, relative prefix to the path, e.g.
                        "/path/to/tensorboard". resulting in the new base url
                        being located at localhost:6006/path/to/tensorboard
                        under default settings. A leading slash is required
                        when specifying the path_prefix, however trailing
                        slashes can be omitted. The path_prefix can be
                        leveraged for path based routing of an elb when the
                        website base_url is not available e.g.
                        "example.site.com/path/to/tensorboard/"           

探尋有趣之事!