前一篇主要對TensorFlow的常量,如簡單的scalar, vector, matrix等Tensor,以及線性序列(Sequence),基本的抽樣函數做了介紹,本篇主要介紹TensorFlow中的變量,數據類型,基本的數學操作,並結合TensorBoard,來介紹一些變量依賴的組織。
搞機器學習或是數值計算程序的人估計都瞭解NumPy,或者整個python-based的數理科學計算的生態系統,SciPy。
數據類型
TensorFlow的基本數據類型在借鑑NumPy(且當前對NumPy的類型幾乎完全兼容)的基礎上,也有些自己原生的一些數據類型,完整的數據類型列表可以參見官網,下表給出一些基本的數據類型:
Data Type | Python type | Description |
---|---|---|
DT_FLOAT | tf.float32 | 32 bits floating point |
DT_DOUBLE | tf.float64 | 64 bits floating point |
DT_INT32 | tf.int32 | 32 bits signed int |
DT_INT64 | tf.int64 | 64 bits signed int |
DT_STRING | tf.string | Variable length byte array |
DT_BOOL | tf.bool | Boolean |
因爲TensorFlow數據類型保持了跟NumPy的無縫集成,大多數時候你可以把NumPy的數據類型當成TensorFlow的來用,但通常的practice是如果可以用TensorFlow原生數據類型的地方,我們就直接用原生的。一方面是誰也不知道現在的版本是兼容的,以後會不會久不兼容了呢?最重要的是,原生的數據類型對TensorFlow的build-in函數,求導優化計算等都有天然的優勢。
變量
前一篇我們介紹了常量,常量跟變量的區別自然不必贅述,就跟任何語言類似。其存儲的地方也不同,比如Java中的常量是放在堆區,而變量是在棧區。在TensorFlow裏,常量和變量也是分開存儲的。常量的值是放在graph的definition裏的,在分佈式環境下,每個節點上整個graph都是replicated的,相應的常量也會replicated一份。對於TensorFlow而言,Graph的definition用protocol buffer來表述:
import tensorflow as tf
vector = tf.constant([2.0, 8], name="vector")
print tf.get_default_graph().as_graph_def()
而變量則不同,往往是放在一些獨立的集羣上 即我們通常所說的Parameter Server,是目前主流的分佈式機器學習框架,原始論文參見,其需要和worker節點進行跨網絡或者RPC通信。
變量聲明
和一般的面嚮對象語言一樣,聲明一個變量就是創建一個tf.Variable
類的實例。和常量不同的是,我們用tf.constant
來聲明一個常量。前者是一個Class,而後者是一個operator(可以看作是一個類裏的方法),一個tf.Variable
類裏可以有多個operator。
import tensorflow as tf
# use InteractiveSession
sess = tf.InteractiveSession()
cons = tf.constant(8, name="consant")
var = tf.Variable(8, name="Variable")
# ==> Tensor("consant:0", shape=(), dtype=int32)
print cons
# ==> <tf.Variable 'Variable:0' shape=() dtype=int32_ref>
print var
變量初始化
在使用一個變量之前,必須先初始化變量,如果使用了一個未初始化的變量,會報一個FailedPreconditionError
的錯誤,如下所示。值得注意的時,和一般的面嚮對象語言不同的是,第3行中,tf.Variable(8,
name="Variable")
,雖然第一個參數是8,似乎是做了初始化,其實不然。前面我們說過,TensorFlow作爲一門工具語言,一個鮮明的特點便是函數(這裏是Graph)的定義和執行是分開的。初始化函數也需要顯示的聲明和執行。
全局初始化函數
import tensorflow as tf
cons = tf.constant(8, name="consant")
var = tf.Variable(8, name="Variable")
init = tf.global_variables_initializer() ## 全局初始化函數聲明
with tf.Session() as sess:
sess.run(init) # 執行全局初始化
print sess.run(cons) # OK, result is 8
# 未初始化: FailedPreconditionError: Attempting to use uninitialized value Variable_2
# 初始化:result is 8.
print sess.run(var)
選擇性初始化
import tensorflow as tf
var1 = tf.Variable(8, name="var1")
var2 = tf.Variable(8, name="var2")
init = tf.variables_initializer([var1]) ## 初始化var1
with tf.Session() as sess:
sess.run(init) # 執行全局初始化
# OK, result is 8
print sess.run(var1)
# 未初始化: FailedPreconditionError: Attempting to use uninitialized value var2_2
print sess.run(var2)
單個變量初始化
import tensorflow as tf
var2 = tf.Variable(8, name="var1")
with tf.Session() as sess:
sess.run(var2.initializer)
print sess.run(var2) # OK, result is 8.
變量評估和賦值
賦值函數assign()
變量聲明之後,我們可以通過在Session中的sess.run()
來查看一個變量的值,還有一個eval()
函數也可以實現該功能。變量的賦值則是通過assign()
函數來實現,值得注意的是這裏的賦值是非引用式的,函數返回賦值後的值,但該變量的值不會改變。
import tensorflow as tf
var1 = tf.Variable(8, name="var1")
var1.assign(100) # 變量賦值,var1 任然是8
init = tf.variables_initializer([var1])
with tf.Session() as sess:
print var1.eval() # OK, result is 8.
值得注意的是在使用了賦值函數後,我們並沒有對var2
進行初始化卻可以正確使用。 查看源碼會發現,其實是assign()
函數替我們做了。當我們通過賦值函數聲明一個變量,但這個變量依賴於另外一個變量時,情況便變得很有趣了。如下所示:
import tensorflow as tf
var1 = tf.Variable(8, name="var1")
var2 = var1.assign(var1*2)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(var1.initializer)
print var2.eval() # result is 16
print var2.eval() # result is 32
print var2.eval() # result is 64
var2被assign的不是一個值,而是一個assign
的operator,因此在Session裏,每次run時就會做一次評估,這就好比C語言中的宏擴展。
自增和自減函數 TensorFlow提供了assign_add()
和assgin_sub()
函數來實現函數的自增自減功能。和assign()函數會自動幫你初始化變量不同,自增、自減函數並不會幫你賦值,你需要自己賦值 原因其均依賴於當前的值做assign,因此需要對var1
和var2
都要做初始化。
TensorBoard
數據可視化在ML裏一直是被忽視但又非常重要的一部分。記得Andrew Ng最常說的一句話便是在做任何數據分析處理之前一定要對數據有個直觀的sense,數據可視化便是重要的方法,因爲其對模型,參數選擇都至關重要。TensorFlow Dev Summit 2017中用很大的篇幅介紹了TensorBoard,如MNIST手寫辨識的demo中長這樣
用Google自己的話說,
"The computations you'll use TensorFlow for -like training a massive deep neural network - can be complex and confusing. To make it easier to understand, debug, and optimize TensorFlow programs, we've included a suite of visualization tools call TensorBoard".
更詳盡的介紹和使用將根據具體的的機器學習的例子來介紹更具有直觀性。最簡單的使用僅兩步:首先在Session裏首行加上,
writer = tf.summary.FileWriter('./graphs', sess.graph)
然後在shell裏run如下命令。打開瀏覽器,http://localhost:6006
,就可以看見針對當前Session的TensorFlow可視化效果。
$ tensorboard --logdir="./graphs"
參考
[2] Tensorflow for Deep Learning Research.