如名稱所示,TensorFlow是定義和運行涉及張量(Tensor)的計算框架。一個張量是將向量和矩陣推廣到潛在更高的維度。在內部,TensorFlow將張量表示為n維基本數據類型的數組。
當編寫一個TensorFlow程序時,你操作和傳遞的主要對象是tf.Tensor
。一個tf.Tensor
對象表示一個部分定義的計算,最終會產生一個值。 TensorFlow程序首先建立基於tf.Tensor
的計算圖,並詳細說明如何根據其他可用張量計算每個張量,然後通過運行該圖的部分來獲得期望的結果。
一個tf.Tensor
具有以下屬性:
- 一個數據類型(例如:
float32
,int32
, 或者string
) - 一個形狀(shape)
張量中的每個元素具有相同的數據類型,並且數據類型總是已知的。形狀(即它具有的維數和每個維度的大小)可能隻是部分已知的。大多數操作都會產生完全已知形狀的張量,如果它們的輸入形狀也是完全已知的,但在某些情況下,隻能在圖形執行時得到張量的形狀。
某些類型的張量是特殊的,這些將在程序員指南的其他單元中介紹。主要的是:
tf.Variable
tf.Constant
tf.Placeholder
tf.SparseTensor
除了tf.Variable
,張量的值是不變的,這意味著在單個執行張量的上下文中隻有一個值。然而,兩次評估相同的張量可以返回不同的值;例如張量可以是從磁盤讀取數據或產生一個隨機數的結果。
秩(rank)
秩是一個tf.Tensor
對象的維數。Rank的同義詞包括order或者degree或者n-dimension。請注意,TensorFlow中的rank與數學中的矩陣rank並不相同。如下表所示,TensorFlow中的每個rank對應於不同的數學實體:
秩(rank) | 數學實體 |
---|---|
0 | 標量(隻有大小) |
1 | 矢量(大小和方向) |
2 | 矩陣(數字表) |
3 | 3-Tensor(數字立方體) |
ñ | n-Tensor(依次類推,你可能已經理解了^_^) |
Rank 0
以下片段演示了創建幾個Rank 0變量:
mammal = tf.Variable("Elephant", tf.string)
ignition = tf.Variable(451, tf.int16)
floating = tf.Variable(3.14159265359, tf.float64)
its_complicated = tf.Variable((12.3, -4.85), tf.complex64)
Rank 1
創建一個Rank 1tf.Tensor
對象,您可以傳遞一個項目列表作為初始值。例如:
mystr = tf.Variable(["Hello"], tf.string)
cool_numbers = tf.Variable([3.14159, 2.71828], tf.float32)
first_primes = tf.Variable([2, 3, 5, 7, 11], tf.int32)
its_very_complicated = tf.Variable([(12.3, -4.85), (7.5, -6.23)], tf.complex64)
更高的Rank
Rank 2tf.Tensor
對象由至少一行和至少一列組成:
mymat = tf.Variable([[7],[11]], tf.int16)
myxor = tf.Variable([[False, True],[True, False]], tf.bool)
linear_squares = tf.Variable([[4], [9], [16], [25]], tf.int32)
squarish_squares = tf.Variable([ [4, 9], [16, 25] ], tf.int32)
rank_of_squares = tf.rank(squarish_squares)
mymatC = tf.Variable([[7],[11]], tf.int32)
Higher-rank張量同樣由n-dimensional數組組成。例如,在圖像處理過程中,使用許多Rank為4的張量,尺寸分別對應於example-in-batch,圖像寬度,圖像高度和顏色通道。
my_image = tf.zeros([10, 299, 299, 3]) # batch x height x width x color
得到一個tf.Tensor
對象的Rank
確定一個tf.Tensor
對象的Rank,使用tf.rank
方法。例如,以下方法以編程方式確定tf.Tensor
的Rank:
r = tf.rank(my3d)
# After the graph runs, r will hold the value 3.
引用tf.Tensor
片段(slices)
由於tf.Tensor
是n維單元格數組,要訪問單個單元格tf.Tensor
你需要指定n個索引。
對於一個Rank 0張量(一個標量),不需要索引,因為它已經是一個單一的數字。
對於Rank 1張量(矢量),傳遞單個索引允許您訪問一個數字:
my_scalar = my_vector[2]
請注意,如果你想動態地從矢量中選擇一個元素,傳入[]
內部的索引本身可以是一個標量tf.Tensor
。
對於Rank 2或更高秩的張量,情況更有趣。對於一個Rank 2的tf.Tensor
,傳遞兩個數字返回一個標量,如預期的那樣:
my_scalar = my_matrix[1, 2]
但是,傳遞一個數字將返回一個矩陣的子向量,如下所示:
my_row_vector = my_matrix[2]
my_column_vector = my_matrix[:, 3]
:
符號是python切片語法,表示“讓這個維度獨立”。這在higher-rank張量中很有用,因為它允許你訪問它的子向量,子矩陣,甚至其他的副本。
形狀(shape)
張量的形狀是每個維度中元素的數量。圖形構建期間,TensorFlow自動推斷形狀。這些推斷的形狀可能具有已知或未知的rank。如果rank已知,則每個維度的大小可能是已知的或未知的。
TensorFlow文檔使用三個符號約定來描述張量維數:rank(秩),shape(形狀)和維數。下表顯示了這些如何相互關聯:
秩 | 形狀 | 維數 | 例子 |
---|---|---|---|
0 | [] | 0-d | 一個0-D張量。一個標量。 |
1 | [D0] | 1-d | 具有形狀[5]的一維張量。 |
2 | [D0,D1] | 2-d | 一個形狀[3,4]二維張量。 |
3 | [D0,D1,D2] | 3-d | 一個形狀[1,4,3]的三維張量。 |
ñ | [D0,D1,… Dn-1] | n-D | 形狀為[D0,D1,… Dn-1]的張量。 |
形狀可以通過Python列表/元組的int或者tf.TensorShape
來表示。
得到一個tf.Tensor
對象的形狀
有兩種方法可以訪問tf.Tensor
的形狀。在建立圖形的時候,了解已知的張量形狀常常是有用的。這可以通過讀取tf.Tensor
對象的shape
屬性。這個方法返回一個TensorShape
對象,這是表示partially-specified(部分指定)形狀的一種方便的方法(因為在構建圖形時,並不是所有的形狀都是完全已知的)。
在運行時,也有可能得到一個tf.Tensor
這將代表另一個的完全已知形狀的tf.Tensor
,通過調用tf.shape
操作。這樣,您就可以構建一個圖,通過構建其他張量來處理張量的形狀,這些張量依賴於輸入的動態形狀tf.Tensor
。
例如,製作與給定矩陣中的列數相同大小的零向量:
zeros = tf.zeros(tf.shape(my_matrix)[1])
改變tf.Tensor
的形狀
張量元素的數量是所有形狀大小的乘積。標量的元素數總是一樣的1
。由於經常有許多不同的形狀具有相同數量的元素,所以通常能夠方便地改變tf.Tensor
形狀,但是保持元素不變。這可以用tf.reshape
來完成。
以下示例演示如何重構(reshape)張量:
rank_three_tensor = tf.ones([3, 4, 5])
matrix = tf.reshape(rank_three_tensor, [6, 10]) # Reshape existing content into
# a 6x10 matrix
matrixB = tf.reshape(matrix, [3, -1]) # Reshape existing content into a 3x20
# matrix. -1 tells reshape to calculate
# the size of this dimension.
matrixAlt = tf.reshape(matrixB, [4, 3, -1]) # Reshape existing content into a
#4x3x5 tensor
# Note that the number of elements of the reshaped Tensors has to match the
# original number of elements. Therefore, the following example generates an
# error because no possible value for the last dimension will match the number
# of elements.
yet_another = tf.reshape(matrixAlt, [13, 2, -1]) # ERROR!
數據類型
除了維度,張量有一個數據類型。
tf.Tensor
不能有多個數據類型。但是,可以將任意數據結構序列化為string
並存儲在tf.Tensor
。
可以使用tf.cast
將tf.Tensor
從一個數據類型強製轉為到另一個:
# Cast a constant integer tensor into floating point.
float_tensor = tf.cast(tf.constant([1, 2, 3]), dtype=tf.float32)
要查看tf.Tensor
的數據類型,使用Tensor.dtype
屬性。
當從一個python對象創建一個tf.Tensor
,你可以選擇指定數據類型。如果你不這樣做,TensorFlow會選擇一個可以表示數據的數據類型。 TensorFlow將Python整數轉換為tf.int32
,將python浮點數字轉為tf.float32
。否則,TensorFlow在轉換為數組時使用與numpy相同的規則。
張量求值
一旦計算圖已經建立,你可以運行計算產生一個特定的tf.Tensor
並獲取分配給它的值。這對於調試以及大部分TensorFlow工作都是非常有用的。
張量取值的最簡單的方法是使用Tensor.eval
方法。例如:
constant = tf.constant([1, 2, 3])
tensor = constant * constant
print tensor.eval()
該eval
方法隻在默認的tf.Session
處於活動狀態時有效。
Tensor.eval
返回與張量相同內容的numpy數組。
有時沒有上下文不可能評估一個tf.Tensor
,因為它的值可能取決於不可用的動態信息。例如,張量依賴於Placeholder
,沒有給Placeholder
提供價值就不能評估。
p = tf.placeholder(tf.float32)
t = p + 1.0
t.eval() # This will fail, since the placeholder did not get a value.
t.eval(feed_dict={p:2.0}) # This will succeed because we're feeding a value
# to the placeholder.
其他模型的構造可能會導致tf.Tensor
的求值變複雜。 TensorFlow無法直接評估在內部函數或內部控製流構造中定義的tf.Tensor
。如果一個tf.Tensor
依賴隊列中的值,隻在有東西入隊才能工作評估tf.Tensor
;否則,評估會掛起。在處理隊列時,在評估tf.Tensor
之前,要調用tf.train.start_queue_runners
。
打印張量
出於調試的目的,你可能想打印一個tf.Tensor
的值。tfdbg提供高級的調試支持,TensorFlow也有一個操作可以直接打印tf.Tensor
的值。
請注意,打印tf.Tensor
時很少使用以下模式:
t = <<some tensorflow operation>>
print t # This will print the symbolic tensor when the graph is being built.
# This tensor does not have a value in this context.
此代碼打印tf.Tensor
對象(表示延遲計算)而不是它的值。相反,TensorFlow提供了tf.Print
操作,它返回其第一個tf.Tensor
參數,並打印第二個tf.Tensor
集合參數。
要正確使用tf.Print
,它的返回值必須被使用。看下麵的例子
t = <<some tensorflow operation>>
tf.Print(t, [t]) # This does nothing
t = tf.Print(t, [t]) # Here we are using the value returned by tf.Print
result = t + 1 # Now when result is evaluated the value of `t` will be printed.