1. 程式人生 > >TensorFlow官方教程學習筆記(一)——起步

TensorFlow官方教程學習筆記(一)——起步

TensorFlow可以拆成兩個詞:Tensor(張量)和Flow(流),Tensor代表最底層的資料結構,每一個Tensor可以簡易的理解為一個多維陣列,類似於Caffe中的Blob,不過與Blob不同的是,對於一張圖片,Tensor的四個維度分別是[batch, height, width, channel](Blob的為[batch, channel, height, width])。Tensor存在於節點op(operation)中,op執行計算功能,值得注意的是,Tensor並不真正具有op的輸出值(it does not hold the values of that operation's output),它只是代表了這個op操作的返回值,它也可以作為另外一個op的輸入。一個Tensor可以在多個op中流動(Flow),這樣就組成了一個圖(Graph),當圖構建好之後,上下文(context)就會啟動一個會話(session)來執行圖中的op,這時Tensor的值才被計算出來。

建立一個預設圖(default graph):

g = tf.Gragh()
with = g.as_default():
它與以下程式碼是等效的:
with tf.Graph().as_default() as g:
這樣context就建立了一個預設圖。

建立好一個預設圖後,就可以通過插入op來構建圖:

g = tf.Gragh()
with = g.as_default():
  matrix1 = tf.constant([[3., 3.]])
  matrix2 = tf.constant([[2.],[2.]])
  product = tf.matmul(matrix1, matrix2)
這裡插入了兩種型別的op:constant和matmul(常量和矩陣相乘),matrix1、matrix2和product代表op返回值的Tensor。

插入op的方式有很多種,如:

tf.Operation.name       #The full name of this operation.
tf.Operation.type       #The type of the op (e.g. "MatMul").
tf.Operation.inputs     #The list of Tensor objects representing the data inputs of this op.

建立好圖後,需要建立一個session來啟動這個圖,例如上面程式碼中,只有在session中啟動這個圖才能真正的進行矩陣相乘的運算,並得到結果:
g = tf.Gragh()
with = g.as_default():
  matrix1 = tf.constant([[3., 3.]])
  matrix2 = tf.constant([[2.],[2.]])
  product = tf.matmul(matrix1, matrix2)
  sess = tf.Session()                      #Construct a `Session` to execut the graph.
  result = sess.run(product)               #Execute the graph and store the value that `product` represents in `result`.
  print result
  sess.close()                             #Close the Session.
sess.run(product)觸發了三個op的執行,返回值 'result' 是一個 numpy `ndarray` 物件。也可以使用以下程式碼來啟動圖:
with tf.Session() as sess:
  result = sess.run(product)
  print result

這樣就可以在會話結束後自動的關閉會話而不需要呼叫close()。

除了sess.run(product)來執行op操作以外,用Tensor的操作product.eval()也可以表達同樣的效果。

對於Tensor的操作有很多種,如:

tf.Tensor.dtype                                 #The DType of elements in this tensor.
tf.Tensor.name                                  #The string name of this tensor.
tf.Tensor.eval(feed_dict=None, session=None)    #Evaluates this tensor in a Session.
tf.Tensor.get_shape()                           #Returns the TensorShape that represents the shape of this tensor.
tf.Tensor.set_shape(shape)                      #Updates the shape of this tensor.
在計算圖時,還可以使用with...device來呼叫特定的CPU或者GPU:
with tf.Session() as sess:
  with tf.device("/gpu:1"):
    matrix1 = tf.constant([[3., 3.]])
    matrix2 = tf.constant([[2.],[2.]])
    product = tf.matmul(matrix1, matrix2)
    ...
這麼多個with,可以把它們合到一起,表達一個完整的計算圖的過程:
g = tf.Graph()
with g.as_default(), g.device('/gpu:1'), tf.Session() as sess:
  matrix1 = tf.constant([[3., 3.]])
  matrix2 = tf.constant([[2.],[2.]])
  product = tf.matmul(matrix1, matrix2)
  result = sess.run(product)
  print result
在TensorFlow中還有一個重要的成員:變數(Variable)

在官方文件中,對變數的說明很簡單:變數維護圖執行過程中的狀態資訊。這可能不太好理解,我的個人理解是,變數實際上就是通過不斷的迭代來更新它的值,最終來滿足模型的條件。一個簡單的例子:
# 建立一個變數, 初始化為標量 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 初始化,
# 首先必須增加一個`初始化` op 到圖中.
init_op = tf.initialize_all_variables()

# 啟動圖, 執行 op
with tf.Session() as sess:
  # 執行 'init' op
  sess.run(init_op)
  # 列印 'state' 的初始值
  print sess.run(state)
  # 執行 op, 更新 'state', 並列印 'state'
  for _ in range(3):
    sess.run(update)
    print sess.run(state)

# 輸出:

# 0
# 1
# 2
# 3
變數存在於記憶體的快取區,它與Tensor是包含的關係,變數在建立之後,必須被顯式的初始化。tf.initialize_all_variables()就是將所有變數初始化的op操作。在session建立之後,需要執行這個op操作。

在整個session執行完之後,可以將變數save,在這之前你需要使用tf.train.Saver()建立一個saver。

# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add an op to initialize the variables.
init_op = tf.initialize_all_variables()

# Add ops to save and restore all the variables.
saver = tf.train.Saver()

# Later, launch the model, initialize the variables, do some work, save the
# variables to disk.
with tf.Session() as sess:
  sess.run(init_op)
  # Do some work with the model.
  ..
  # Save the variables to disk.
  save_path = saver.save(sess, "/tmp/model.ckpt")
  print "Model saved in file: ", save_path
你也可以對一個已存有的變數進行restore,這裡不需要再進行初始化:
# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add ops to save and restore all the variables.
saver = tf.train.Saver()

# Later, launch the model, use the saver to restore variables from disk, and
# do some work with the model.
with tf.Session() as sess:
  # Restore variables from disk.
  saver.restore(sess, "/tmp/model.ckpt")
  print "Model restored."
  # Do some work with the model
  ...
當然你也可以選擇某一個變數進行儲存:
# Create some variables.
v1 = tf.Variable(..., name="v1")
v2 = tf.Variable(..., name="v2")
...
# Add ops to save and restore only 'v2' using the name "my_v2"
saver = tf.train.Saver({"my_v2": v2})
# Use the saver object normally after that.
...
在Tensor的操作中有一個很重要的機制:feed,它實際上起著替換的作用,常常用來為run()、eval()中的Tensor提供資料,不過前提是這個需要為這些Tensor建立佔位符:tf.placeholder()。具體的使用方法如下:
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.mul(input1, input2)

with tf.Session() as sess:
  print sess.run([output], feed_dict={input1:[7.], input2:[2.]})

# 輸出:
# [array([ 14.], dtype=float32)]
程式碼中,feed_dict的作用就是將[7.]傳遞給input1,將[2.]傳遞給input2,從而來進行run()的操作。

值得注意的是,如果你使用tf.placeholder()建立了佔位符,而並沒有正確的為它提供feed,將會產生很嚴重的錯誤。