TensorFlow 學習小結(2) - 基本用法

需要理解在TensorFlow中,是如何:

  • 將計算流程表示成圖;
  • 通過Sessions來執行圖計算;
  • 將數據表示爲tensors;
  • 使用Variables來保持狀態信息;
  • 分別使用feeds和fetches來填充數據和抓取任意的操作結果;

接下來看具體概念:

  • TensorFlow 用圖來表示計算任務,圖中的節點被稱之爲operation,縮寫成op。
  • 一個節點獲得 0 個或者多個張量 tensor,執行計算,產生0個或多個張量。

圖必須在會話(Session)裏被啓動,會話(Session)將圖的op分發到CPU或GPU之類的設備上,同時提供執行op的方法,這些方法執行後,將產生的張量(tensor)返回。

概念描述

張量(Tensor)

其實就是指矩陣。也可以理解爲tensorflow中矩陣的表示形式。Tensor的生成方式有很多種,最簡單的就如

port tensorflow as tf # 在下面所有代碼中,都去掉了這一行,默認已經導入
a = tf.zeros(shape=[1,2])

不過要注意,因爲在訓練開始前,所有的數據都是抽象的概念,也就是說,此時a只是表示這應該是個1*5的零矩陣,而沒有實際賦值,也沒有分配空間,所以如果此時print,就會出現如下情況:

print(a) #===>Tensor("zeros:0",shape=(1, 2), dtype=float32)

只有在訓練過程開始後,才能獲得a的實際值

sess = tf.InteractiveSession()
print(sess.run(a))
#===>[[ 0.  0.]]

這邊設計到Session概念,後面會提到

變量(Variable)

一般用來表示圖中的各計算參數,包括矩陣,向量等。例如,要表示線性相關的數據模型,那表達式就是

y=Relu(Wx+b)

這裏W和b是要用來訓練的參數,Relu()是激活函數,那麼此時這兩個值就可以用Variable來表示。Variable的初始函數有很多其他選項,這裏先不提,只輸入一個Tensor也是可以的

W = tf.Variable(tf.zeros(shape=[1,2]))

注意,此時W一樣是一個抽象的概念,而且與Tensor不同,Variable必須初始化以後纔有具體的值。

tensor = tf.zeros(shape=[1,2])
variable = tf.Variable(tensor)
sess = tf.InteractiveSession()
#print(sess.run(variable))  # 會報錯

sess.run(tf.initialize_all_variables())
# 對variable進行初始化

print(sess.run(variable))
#===>[[ 0.  0.]]

佔位符(placeholder)

是一個抽象的概念。用於表示輸入輸出數據的格式。告訴系統:這裏有一個值/向量/矩陣,現在沒法給你具體數值,不過在正式運行的時候會補上的!例如上式中的x和y。因爲沒有具體數值,所以只要指定尺寸即可

x = tf.placeholder(tf.float32,[1, 5],name='input')
y = tf.placeholder(tf.float32,[None,5],name='input')

上面有兩種形式,第一種x,表示輸入是一個[1,5]的橫向量。

而第二種形式,表示輸入是一個[?,5]的矩陣。那麼什麼情況下會這麼用呢?就是需要輸入一批[1,5]的數據的時候。比如我有一批共10個數據,那我可以表示成[10,5]的矩陣。如果是一批5個,那就是[5,5]的矩陣。tensorflow會自動進行批處理。

會話(Session)

session是抽象模型的實現者。爲什麼之前的代碼多處要用到session?因爲模型是抽象的嘛,只有實現了模型以後,才能夠得到具體的值。同樣,具體的參數訓練,預測,甚至變量的實際值查詢,都要用到session,看後面就知道了。

用法說明

構造階段(construction phase)

組裝計算圖

計算圖(graph):要組裝的結構。由許多操作組成。
操作(ops):接受零個或多個輸入,返回零個或多個輸出。
數據類型:主要分爲張量(tensor)、變量(variable)和常量(constant)
張量:多維array或list

創建語句:

tensor_name=tf.placeholder(type,shape, name)

placeholder叫佔位符,同樣是一個抽象的概念。用於表示輸入輸出數據的格式。告訴系統:這裏有一個值/向量/矩陣,現在沒法給出具體數值,不過在正式運行的時候會補上的!

變量:在同一時刻對圖中所有其他操作都保持靜態的數據
創建語句:

name_variable = tf.Variable(value, name)

初始化語句:

#個別變量
init_op=variable.initializer()

#所有變量
init_op=tf.initialize_all_variables()

#注意:init_op的類型是操作(ops),加載之前並不執行

更新語句:

update_op=tf.assign(variable to be updated, new_value)

常量:無需初始化的變量
創建語句:

name_constant=tf.constant(value)

執行階段(execution phase)

使用計算圖

會話:執行(launch)構建的計算圖。可選擇執行設備:單個電腦的CPU、GPU,或電腦分佈式甚至手機。

創建語句:

#常規
sess = tf.Session()

#交互
sess = tf.InteractiveSession()

#交互方式可用tensor.eval()獲取值,ops.run()執行操作
#關閉
sess.close()

執行操作:使用創建的會話執行操作
執行語句:

sess.run(op)

送值(feed):輸入操作的輸入值
語句:

sess.run([output],feed_dict={input1:value1, input2:value1})

取值(fetch):獲取操作的輸出值
語句:

#單值獲取
sess.run(one op)

#多值獲取
sess.run([a list of ops])

創建一個 Session 對象, 如果無任何創建參數, 會話構造器將啓動默認圖。
會話負責傳遞 op 所需的全部輸入,op 通常是併發執行的。

# 啓動默認圖.
sess = tf.Session()

# 調用sess 的 'run()' 方法,傳入 'product' 作爲該方法的參數,
# 觸發了圖中三個op (兩個常量 op 和一個矩陣乘法op),
# 向方法表明,希望取回矩陣乘法op 的輸出.
result = sess.run(product)

# 返回值'result' 是一個 numpy `ndarray` 對象.
print result
# ==> [[ 12.]]

# 任務完成,需要關閉會話以釋放資源。
sess.close()

下面代碼中有tf.initialize_all_variables,是預先對變量初始化,Tensorflow 的變量必須先初始化,然後纔有值!而常值張量是不需要的。即使是assign() 操作和 add() 操作,在調用 run() 之前,
它並不會真正執行賦值和相加操作。

上面的代碼定義了一個如下的計算圖:
在這裏插入圖片描述
總結一下,來一個清晰的代碼:

過程就是:建圖->啓動圖->運行取值

計算矩陣相乘:

import tensorflow as tf

# 建圖
matrix1 = tf.constant([[3.,3.]])
matrix2 = tf.constant([[2.],[2.]])
product = tf.matmul(matrix1, matrix2)

# 啓動圖
sess = tf.Session()

# 取值
result = sess.run(product)print
resultsess.close()

常用函數

算術操作函數

tf.add(x, y, name=None) 求和
tf.sub(x, y, name=None) 減法
tf.mul(x, y, name=None) 乘法
tf.div(x, y, name=None) 除法
tf.mod(x, y, name=None) 取模
tf.abs(x, name=None) 求絕對值
tf.neg(x, name=None) 取負 (y = -x).
tf.sign(x, name=None) 返回符號 y = sign(x)= -1 if x < 0; 0 if x == 0; 1 if x > 0.
tf.inv(x, name=None) 取反
tf.square(x, name=None) 計算平方 (y = x * x = x^2).
tf.round(x, name=None) 舍入最接近的整數
tf.sqrt(x, name=None) 開根號 (y = \sqrt{x} = x^{1/2}).
tf.pow(x, y, name=None) 冪次方
tf.exp(x, name=None) 計算e的次方
tf.log(x, name=None) 計算log,一個輸入計算e的ln,兩輸入以第二輸入爲底
tf.maximum(x, y, name=None) 返回最大值 (x > y ? x : y)
tf.minimum(x, y, name=None) 返回最小值 (x < y ? x : y)

數據類型轉換

tf.string_to_number(string_tensor, out_type=None, name=None) 字符串轉爲數字
tf.to_double(x, name=’ToDouble’) 轉爲64位浮點類型–float64
tf.to_float(x, name=’ToFloat’) 轉爲32位浮點類型–float32
tf.to_int32(x, name=’ToInt32’) 轉爲32位整型–int32
tf.to_int64(x, name=’ToInt64’) 轉爲64位整型–int64
tf.cast(x, dtype, name=None) 將x或者x.values轉換爲dtype

# tensor a is [1.8, 2.2],dtype=tf.float
tf.cast(a, tf.int32) ==> [1, 2]  # dtype=tf.int32 

矩陣操作

tf.ones | tf.zeros
tf.ones(shape,type=tf.float32,name=None)
tf.zeros([2, 3], int32)
用法類似,都是產生尺寸爲shape的張量(tensor)。

tf.ones_like | tf.zeros_like
tf.ones_like(tensor,dype=None,name=None)
tf.zeros_like(tensor,dype=None,name=None)
新建一個與給定的tensor類型大小一致的tensor,其所有元素爲1和0。

tf.fill
tf.fill(shape,value,name=None)
創建一個形狀大小爲shape的tensor,其初始值爲value
print(sess.run(tf.fill([2,3],2))) #[[2 2 2], # [2 2 2]]

tf.constant
tf.constant(value,dtype=None,shape=None,name=’Const’)
創建一個常量tensor,按照給出value來賦值,可以用shape來指定其形狀。value可以是一個數,也可以是一個list。

如果是一個數,那麼這個常亮中所有值的按該數來賦值。
如果是list,那麼len(value)一定要小於等於shape展開後的長度。賦值時,先將value中的值逐個存入。不夠的部分,則全部存入value的最後一個值。

tf.random_normal | tf.truncated_normal | tf.random_uniform
tf.random_normal(shape,mean=0.0,stddev=1.0,dtype=tf.float32,seed=None,name=None)
tf.truncated_normal(shape, mean=0.0,
stddev=1.0, dtype=tf.float32, seed=None, name=None)
tf.random_uniform(shape,minval=0,maxval=None,dtype=tf.float32,seed=None,name=None)
這幾個都是用於生成隨機數tensor的。尺寸是shape

random_normal: 正太分佈隨機數,均值mean,標準差stddev
truncated_normal:截斷正態分佈隨機數,均值mean,標準差stddev,不過只保留[mean-2stddev,mean+2stddev]範圍內的隨機數
random_uniform:均勻分佈隨機數,範圍爲[minval,maxval]。

tf.get_variable
get_variable(name, shape=None, dtype=dtypes.float32, initializer=None, regularizer=None, trainable=True, collections=None, caching_device=None, partitioner=None, validate_shape=True, custom_getter=None):
如果在該命名域中之前已經有名字=name的變量,則調用那個變量;如果沒有,則根據輸入的參數重新創建一個名字爲name的變量。

name: 這個不用說了,變量的名字
shape: 變量的形狀,[]表示一個數,[3]表示長爲3的向量,[2,3]表示矩陣或者張量(tensor)
dtype: 變量的數據格式,主要有tf.int32, tf.float32, tf.float64等等

initializer: 初始化工具,有tf.zero_initializer, tf.ones_initializer, tf.constant_initializer, tf.random_uniform_initializer, tf.random_normal_initializer, tf.truncated_normal_initializer等

tf.shape
tf.shape(Tensor)
Returns the shape of a tensor.返回張量的形狀。但是注意,tf.shape函數本身也是返回一個張量。而在tf中,張量是需要用sess.run(Tensor)來得到具體的值的。

tf.expand_dims
tf.expand_dims(Tensor, dim) 爲張量 +1維。

tf.pack
tf.pack(values,axis=0, name=”pack”)
Packs a list of rank-R tensors into one rank-(R+1) tensor
將一個R維張量列表沿着axis軸組合成一個R+1維的張量。

tf.concat
tf.concat(concat_dim, values, name=”concat”)
Concatenates tensors along one dimension.
將張量沿着指定維數拼接起來。

tf.sparse_to_dense
稀疏矩陣轉密集矩陣
定義爲:
def sparse_to_dense(sparse_indices, output_shape, sparse_values, default_value=0, validate_indices=True, name=None):

幾個參數的含義:
sparse_indices: 元素的座標[[0,0],[1,2]]表示(0,0),和(1,2)處有值
output_shape:得到的密集矩陣的shape
sparse_values: sparse_indices座標表示的點的值,可以是0D或者1D張量。若0D,則所有稀疏值都一樣。若是1D,則len(sparse_values)應該等於len(sparse_indices)
default_values: 缺省點的默認值

tf.random_shuffle
tf.random_shuffle(value,seed=None,name=None)
沿着value的第一維進行隨機重新排列。

tf.argmax | tf.argmin
tf.argmax(input=tensor,dimention=axis)
找到給定的張量tensor中在指定軸axis上的最大值/最小值的位置。

tf.equal
tf.equal(x, y, name=None):
判斷兩個tensor是否每個元素都相等。返回一個格式爲bool的tensor

tf.cast
cast(x, dtype, name=None)
將x的數據格式轉化成dtype.例如,原來x的數據格式是bool,那麼將其轉化成float以後,就能夠將其轉化成0和1的序列。反之也可以。

tf.matmul
用來做矩陣乘法。若a爲lm的矩陣,b爲mn的矩陣,那麼通過tf.matmul(a,b)
結果就會得到一個l*n的矩陣
不過這個函數還提供了很多額外的功能。我們來看下函數的定義:
matmul(a, b, transpose_a=False, transpose_b=False, a_is_sparse=False, b_is_sparse=False, name=None):
可以看到還提供了transpose和is_sparse的選項。
如果對應的transpose項爲True,例如transpose_a=True,那麼a在參與運算之前就會先轉置一下。
而如果a_is_sparse=True,那麼a會被當做稀疏矩陣來參與運算。

tf.reshape
reshape(tensor, shape, name=None)
顧名思義,就是將tensor按照新的shape重新排列。一般來說,shape有三種用法:
如果 shape=[-1], 表示要將tensor展開成一個list
如果 shape=[a,b,c,…] 其中每個a,b,c,…均>0,那麼就是常規用法
如果 shape=[a,-1,c,…] 此時b=-1,a,c,…依然>0。這表示tf會根據tensor的原尺寸,自動計算b的值。

其他常用操作

tf.linspace | tf.range
tf.linspace(start,stop,num,name=None)
tf.range(start,limit=None,delta=1,name=’range’)
這兩個放到一起說,是因爲他們都用於產生等差數列,不過具體用法不太一樣。
tf.linspace在[start,stop]範圍內產生num個數的等差數列。不過注意,start和stop要用浮點數表示,不然會報錯
tf.range在[start,limit)範圍內以步進值delta產生等差數列。注意是不包括limit在內的。

tf.assign
tf.assign(ref, value, validate_shape=None, use_locking=None, Name=None)
tf.assign是用來更新模型中變量的值的。ref是待賦值的變量,value是要更新的值。即效果等同於 ref = value 。

簡單實例

通過幾個例子瞭解了基本的用法。

生成三維數據後使用平面擬合

import tensorflow as tf
import numpy as np

# 用NumPy 隨機生成 100 個數據
x_data = np.float32(np.random.rand(2, 100)) 
y_data = np.dot([0.100, 0.200], x_data) + 0.300

# 構造一個線性模型
b = tf.Variable(tf.zeros([1]))
W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0))
y = tf.matmul(W, x_data) + b

# 最小化方差
loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

# 初始化變量
init = tf.initialize_all_variables()

# 啓動圖 (graph)
sess = tf.Session()
sess.run(init)

# 擬合平面
for step in xrange(0, 201):
    sess.run(train)
    if step % 20 == 0:
        print step, sess.run(W), sess.run(b)

# 輸出結果爲:
0 [[-0.14751725  0.75113136]] [ 0.2857058]
20 [[ 0.06342752  0.32736415]] [ 0.24482927]
40 [[ 0.10146417  0.23744738]] [ 0.27712563]
60 [[ 0.10354312  0.21220125]] [ 0.290878]
80 [[ 0.10193551  0.20427427]] [ 0.2964265]
100 [[ 0.10085492  0.201565 ]] [ 0.298612]
120 [[ 0.10035028  0.20058727]] [ 0.29946309]
140 [[ 0.10013894  0.20022322]] [ 0.29979277]
160 [[ 0.1000543   0.20008542]] [ 0.29992008]
180 [[ 0.10002106  0.20003279]] [ 0.29996923]
200 [[ 0.10000814  0.20001261]] [ 0.29998815]

計算矩陣相乘

import tensorflow as tf

# 創建一個 常量op, 返回值 'matrix1' 代表這個1x2 矩陣.
matrix1 = tf.constant([[3.,3.]])

# 創建另外一個 常量op, 返回值 'matrix2' 代表這個2x1 矩陣.
matrix2 = tf.constant([[2.],[2.]])

# 創建一個矩陣乘法 matmul op , 把 'matrix1' 和 'matrix2' 作爲輸入.
# 返回值 'product' 代表矩陣乘法的結果.
product = tf.matmul(matrix1, matrix2)

計算 ‘x’ 減去 ‘a’

# 進入一個交互式 TensorFlow 會話.
import tensorflow as tf
sess = tf.InteractiveSession()
x = tf.Variable([1.0, 2.0])
a = tf.constant([3.0, 3.0])

# 使用初始化器 initializer op 的 run() 方法初始化'x' 
x.initializer.run()

# 增加一個減法 sub op, 從 'x' 減去'a'. 運行減法 op, 輸出結果 
sub = tf.sub(x, a)
print sub.eval()
# ==> [-2. -1.]

使用變量實現一個簡單的計數器

# -創建一個變量,初始化爲標量 0. 初始化定義初值
state = tf.Variable(0, name="counter")

# 創建一個op, 其作用是使 state 增加1
one = tf.constant(1)
new_value = tf.add(state,one)
update = tf.assign(state,new_value)

# 啓動圖後,變量必須先經過`初始化`(init) op 初始化, 才真正通過Tensorflow的#initialize_all_variables對這些變量賦初值
init_op = tf.initialize_all_variables()

# 啓動默認圖,運行 op
with tf.Session() as sess:  

# 運行'init' op  
sess.run(init_op)  

# 打印 'state' 的初始值 
# 取回操作的輸出內容,可以在使用 Session 對象的run() 調用 執行圖時, 傳入一些 #tensor, 這些 tensor 會幫助你取回結果.此處只取回了單個節點state,也可以在運行一次 op 時一起取回多個 tensor: result =sess.run([mul, intermed])  
print sess.run(state)  

# 運行 op, 更新 'state', 並打印 'state'  
for_in range(3):    
         sess.run(update)    
         print sess.run(state) 

# 輸出:
# 0
# 1
# 2
# 3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章