當前位置: 首頁>>技術教程>>正文


TensorFlow編程指南: Tensor(張量)

如名稱所示,TensorFlow是定義和運行涉及張量(Tensor)的計算框架。一個張量是將向量和矩陣推廣到潛在更高的維度。在內部,TensorFlow將張量表示為n維基本數據類型的數組。

當編寫一個TensorFlow程序時,你操作和傳遞的主要對象是tf.Tensor。一個tf.Tensor對象表示一個部分定義的計算,最終會產生一個值。 TensorFlow程序首先建立基於tf.Tensor的計算圖,並詳細說明如何根據其他可用張量計算每個張量,然後通過運行該圖的部分來獲得期望的結果。

一個tf.Tensor具有以下屬性:

  • 一個數據類型(例如:float32int32, 或者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.casttf.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.

參考資料

本文由《純淨天空》出品。文章地址: https://vimsky.com/zh-tw/article/3649.html,未經允許,請勿轉載。