TensorFlow入門(二) TensorFlow數據模型——張量

1.2 TensorFlow數據模型——張量

1.2.1 張量的概念

在TensorFlow程序中,所有的數據都通過張量的形式來表示。從功能角度上看,張量可以簡單理解爲多維數組,其中零階張量表示爲標量(scalar),也就是一個數(張量的類型也可以是字符串);第一階張量爲向量(vector),也就是一個一維數組;第n階張量可以理解爲一個n維數組。但張量在TensorFlow中的實現並不是直接採用數組的形式,它只是對TensorFlow中運算結果的引用。在張量中並沒有真正保存數字,它保存的是如何得到這些數字的計算過程。還是以向量加法爲例,當運行如下代碼時,並不會得到加法的結果,而會得到對結果的一個引用。

import tensorflow as tf
# tf.constant是一個計算,這個計算的結果爲一個張量,保存在變量a中
a = tf.constant([1.0, 2.0], name="a")
b = tf.constant([2.0, 3.0], name="b")
result = tf.add(a, b, name="add")
print(result)
"""
輸出:
Tensor("add:0", shape(2,), dtype=float32)
"""

從上面的代碼可以看出TensorFlow中的張量和NumPy中的數組不同,TensorFlow計算的結果不是一個具體的數字,而是一個張量的結構。從上面的代碼的運行結果可以看出,一個張量中主要保存了三個屬性:名字(name),維度(shape)和類型(type)。


張量的第一個屬性名字不僅是一個張量的唯一標識符,它同樣也給出了這個張量是如何計算出來的。TensorFlow的計算都可以通過計算圖的模型來建立,而計算圖上的每一個節點代表了一個計算,計算結果就保存在張量之中。所以張量和計算圖上節點所代表的計算結果是對應的。這樣張量的命名就可以通過“node:src_output”的形式來給出。其中node爲節點的名稱,src_output表示當前張量來自節點的第幾個輸出。比如上面代碼打出來的“add:0”就說明了result這個張量是計算節點“add”輸出的第一個結果(編號從0開始)。


張量的第二個屬性是張量的維度(shape)。這個屬性描述了一個張量的維度信息。比如上面樣例中shape=(2,)說明了張量result是一個一維數組,這個數組的長度爲2。維度是張量一個很重要的屬性,圍繞張量的維度TensorFlow也給出很多有用的運算。
張量的第三個屬性是類型(type),每一個張量會有一個唯一的類型。TensorFlow會對參與運算的所有張量進行類型的檢查,當發現類型不匹配時會報錯。比如運行下面這段程序就會得到類型不匹配的錯誤:

import tensorflow as tf
a = tf.constant([1, 2], name="a")
b = tf.constant([2.0, 3.0], name="b")
result = a + b

這段程序和上面的樣例基本一模一樣,唯一不同的是把其中一個加數的小數點去掉了。這會使得加數a的類型爲整數而加數b的類型爲實數,這樣程序會報類型不匹配的錯誤:

ValueError: Tensor conversion requested dtype int32 for Tensor with dtype float32: 'Tensor("b:0", shape=(2,), dtype=float32)

如果將一個加數指定成實數類型“a = tf.constant([1, 2], name="a", dtype=tf.float32)”,那麼兩個加數的類型相同就不會報錯了。如果不指定類型,TensorFlow會給出默認的類型,比如不帶小數點的類型會被默認爲int32,帶小數的會默認爲float32。因爲使用默認類型有可能會導致潛在的類型不匹配問題,所以一般建議通過指定dtype來明確指出變量或者常量的類型。TensorFlow支持14種不同的類型,主要包括了實數(tf.float32、tf.float64)、整數(tf.int8、tf.int16、tf.int32、tf.int64、tf.uint8)、布爾型(tf.bool)和複數(tf.complex64、tf.complex128)。

1.2.2 張量的使用

和TensorFlow的計算模型相比,TensorFlow的數據模型相對比較簡單。張量使用主要可以總結爲兩大類。

第一類用途是對中間結果的引用。當一個計算包含很多中間結果時,使用張量可以大大提高代碼的可讀性。以下爲使用張量和不使用張量記錄中間結果來完成向量加法的功能的代碼對比。

# 使用張量記錄中間結果
a = tf.constant([1.0, 2.0], name="a")
b = tf.constant([2.0, 3.0], name="b")
result = a + b

# 直接計算向量的和,這樣可讀性會較差
result = tf.constant([1.0, 2.0], name="a") + 
         tf.constant([2.0, 3.0], name="b")

從上面的樣例程序可以看到a和b其實就是對常量生成這個運算結果的引用,這樣在做加法時(比如在構建深層神經網絡時)通過張量來引用計算的中間結果可以使代碼的可閱讀性大大提升。同樣通過張量來存儲中間結果,這樣可以方便獲取中間結果。比如在卷積神經網絡中,卷積層或者池化層有可能改變張量的維度,通過result.get_shape函數來獲取結果張量的維度信息可以免去人工計算的麻煩。


使用張量的第二類情況是當計算圖構造完成之後,張量可以用來獲得計算結果,也就是得到真實的數字。雖然張量本身沒有存儲具體的數字,但是通過會話(session),就可以得到這些具體的數字。比如在上述代碼中,可以使用 tf.Session().run(result) 語句來得到計算結果。

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