TensorFlow ABC2

by allenlu2007

Ref: http://wiki.jikexueyuan.com/project/tensorflow-zh/get_started/basic_usage.html

本文摘自 TensorFlow 官方文件。比前文更正確。

 

基本使用

使用 TensorFlow, 你必须明白 TensorFlow:

  • 使用 graph 来表示計算任務.
  • 在 Session 的上下文 (context) 中執行 graph.
  • 使用 tensor 表示 data.
  • 通過 Variables 維護狀態.
  • 使用 feed 和 fetch 可以為任意的操作(arbitrary operation) 赋值或者從其中獲取 data.

 

综述

TensorFlow 是一個编程系统, 使用graph来表示計算任務.  Graph中的節點被稱之為 op (operation 的缩寫). 一個 op 獲得 0 個或多個 Tensor, 執行計算, 產生 0 個或多個 Tensor.  每個 Tensor 是一個 multi-dimension numerical array.  例如, 你可以將一小 batch graph pixel 表示為一個 4 dimension floating point data, 這四個维度分别是 [batch, height, width, channels (e.g. RGB channel)].

一個 TensorFlow graph描述了計算的過程. 為了進行計算, graph 必须在 Session 中啟動.  Session 將graph的 op 分發到诸如 CPU 或 GPU 之類的 Device 上, 同时提供執行 op 的方法.  這些方法執行后, 將產生的 tensor 返回.  在 Python 语言中, 返回的 tensor 是 numpy ndarray object; 在 C 和 C++ 语言中, 返回的 tensor 是 tensorflow::Tensor.

Computation Graph

TensorFlow 程序通常包含:一個構建階段和一個執行階段.

在構建階段, op 的執行步骤 被描述成一個graph.

在執行階段, 使用 session 執行 graph 中的 op.

通常在構建階段創建一個 graph 来表示 (represent) 和训练 (train) 一個神经网络, 然后在執行階段反複執行 graph 中的训练 op.

TensorFlow 支持 C, C++, Python. 目前, TensorFlow 的 Python library 更加易用, 它提供了大量的辅助函数来簡化構建graph的工作, 這些函数尚未被 C 和 C++ libraries 支持.

三种语言的會話庫 (session libraries) 是一致的.

構建 Graph

構建 graph 的第一步, 是創建 source op.  Source op 不需要任何输入, 例如 常量 (Constant).  Source op 的输出被傳给其它 op 做運算.

Python library, op 構造器的返回值代表被構造出的 op 的输出, 這些返回值可以傳遞给其它 op 構造器作為输入.

TensorFlow Python library 有一個 default graph, op 構造器可以為其增加節點. 這個 default graph 對许多程序来说已经足够用了. 阅讀 Graph Class 文件来了解如何管理多個 graphs.

 
import tensorflow as tf 
# 創建一個常量 op, 產生一個 1x2 矩陣. 這個 op 被作為一個節點 
# 加到 default graph 中. 
# 
# 構造器的返回值代表该常量 op 的返回值. 
matrix1 = tf.constant([[3., 3.]])

# 創建另外一個常量 op, 產生一個 2x1 矩陣. 
matrix2 = tf.constant([[2.],[2.]])

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

 

Default graph 现在有三個節點, 两個 constant() op, 和一個matmul() op. 為了真正進行矩陣相乘運算, 并得到矩陣乘法的结果, 必须在 session 中啟動這個 graph.

在一個 Session 中啟動 Graph

構造階段完成后, 才能啟動graph. 啟動 graph 的第一步是創建一個 Session object, 如果無任何創建参数, session 構造器將啟動 default graph.

欲了解完整的 Session API, 请阅讀 Session Class.

# 啟動 default graph. 
sess = tf.Session() 
# 調用 sess 的 'run()’ method 来執行矩陣乘法 op, 傳入 'product’ 作為 method 的参数. 
# 上面提到, 'product' 代表了矩陣乘法 op 的输出, 傳入它是向 method 表明, 我们希望取回 
# 矩陣乘法 op 的输出. 
# 
# 整個執行過程是自動化的, session 负责傳遞 op 所需的全部输入. op 通常是平行執行的. 
# 
# 函数調用 'run(product)’ 触發了graph中三個 op (两個常量 op 和一個矩陣乘法 op) 的執行. 
# 
# 返回值 'result' 是一個 numpy `ndarray` object. 
result = sess.run(product) 
print result 
# ==> [[ 12.]]
 
# 任務完成, 關閉 Session. 
sess.close()
 

Session object 在使用完后需要關閉以釋放资源. 除了顯式調用 close 外, 也可以使用 “with” 代码塊自動完成關閉動作.

with tf.Session() as sess:
 result = sess.run([product])
 print result
 

在實现上, TensorFlow 將 graph form 轉换成分布式執行, 以充分利用可用的計算资源(如 CPU 或 GPU). 一般不需要特別指定使用 CPU 還是 GPU, TensorFlow 能自動檢测. 如果檢测到 GPU, TensorFlow 會儘可能地利用找到的第一個 GPU 来執行操作.

如果有超過一個可用的 GPU, 除第一個外,其它 GPU by default 是不用的. 為了讓 TensorFlow 使用這些 GPU, 你必须將 op 明確指派给它们執行. 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)
 ...

設備用 char string 進行標識. 目前支持的設備包括:

  • "/cpu:0": 機器的 CPU.
  • "/gpu:0": 機器的第一個 GPU, 如果有的話.
  • "/gpu:1": 機器的第二個 GPU, 以此類推.

阅讀使用GPU章節, 了解 TensorFlow GPU 使用的更多資訊.

 

交互式使用

文檔中的 Python 示例使用一個 Session 来啟動 graph, 并調用 Session.run() method 執行操作.

為了便于使用诸如 IPython 之類的 Python 交互環境, 可以使用 InteractiveSession 代替 Session 類, 使用 Tensor.eval() 和 Operation.run() method代替 Session.run(). 這樣可以避免使用一個變量来持有 session.

# 進入一個交互式 TensorFlow session. 
import tensorflow as tf 
sess = tf.InteractiveSession()
 
x = tf.Variable([1.0, 2.0]) 
a = tf.constant([3.0, 3.0])
 
# 使用初始化器 initializer op 的 run() method初始化 'x' 
x.initializer.run()
 
# 增加一個减法 sub op, 從 'x' 减去 'a'. 運行减法 op, 输出结果 
sub = tf.sub(x, a) 
print sub.eval() 
# ==> [-2. -1.]

 

Tensor

TensorFlow 程序使用 tensor data structure 来代表所有的 data, 計算 graph 中, 操作间傳遞的 data 都是 tensor.  你可以把 TensorFlow tensor 看作是一個 n-dimension numeric array or table.  一個 tensor 包含一個静態類型 rank, 和一個 shape.  想了解 TensorFlow 是如何处理這些概念的, 参见 Rank, Shape, 和 Type.

 

變量

Variables 维護 graph 執行過程中的状態信息. 下面的例子演示了如何使用變量實现一個簡单的計数器. 参见變量章節了解更多细節.

# 創建一個變量, 初始化為標量 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)
 
# 啟動 graph 后, 變量必须先经過`初始化` (init) op 初始化, 
# 首先必须增加一個`初始化` op 到graph中. 
init_op = tf.initialize_all_variables()
 
# 啟動graph, 運行 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

代码中 assign() 操作是 graph 所描繪的表达式的一部分, 正如 add() 操作一樣. 所以在調用 run() 執行表达式之前, 它并不會真正執行赋值操作.

通常會將一個统計模型中的参数表示為一组變量. 例如, 你可以將一個神经网络的權重作為某個變量存储在一個 tensor 中. 在训练過程中, 通過重複運行训练 graph, 更新這個 tensor.

 

Fetch

為了取回操作的输出内容, 可以在使用 Session 對象的 run() 調用 執行 graph 时, 傳入一些 tensor, 這些 tensor 會帮助你取回结果. 在之前的例子里, 我们只取回了单個節點 state, 但是你也可以取回多個 tensor:

input1 = tf.constant(3.0) 
input2 = tf.constant(2.0) 
input3 = tf.constant(5.0) 
intermed = tf.add(input2, input3) 
mul = tf.mul(input1, intermed)
 
with tf.Session() as sess:
 result = sess.run([mul, intermed])
 print result 
 
# 输出:
# [array([ 21.], dtype=float32), array([ 7.], dtype=float32)]

需要獲取的多個 tensor 值,在 op 的一次運行中一起獲得(而不是逐個去獲取 tensor)。

 

Feed

上述示例在計算graph中引入了 tensor, 以常量或變量的形式存储. TensorFlow 還提供了 feed 機制, 该機制可以臨时替代graph中的任意操作中的 tensor 可以對 graph 中任何操作提交 patch, 直接插入一個 tensor.

feed 使用一個 tensor 值臨时替换一個操作的输出结果. 你可以提供 feed data作為 run() 調用的参数. Feed 只在調用它的method内有效, method结束, feed 就會消失. 最常见的用例是將某些特殊的操作指定為 “feed” 操作, 標记的方法是使用 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)]
 

for a larger-scale example of feeds. 如果没有正確提供 feed, placeholder() 操作將會產生错误. MNIST 全连通 feed 教程 (source code) 给出了一個更大规模的使用 feed 的例子.

Advertisements