TensorFlow 是由谷歌在 2015 年 11 月發佈的深度學習開源工具,咱們能夠用它來快速構建深度神經網絡,並訓練深度學習模型。運用 TensorFlow 及其餘開源框架的主要目的,就是爲咱們提供一個更利於搭建深度學習網絡的模塊工具箱,使開發時可以簡化代碼,最終呈現出的模型更加簡潔易懂。編程
2019 年,TensorFlow 推出了 2.0 版本,也意味着 TensorFlow 從 1.x 正式過分到 2.x 時代。根據 TensorFlow 官方 介紹內容 顯示,2.0 版本將專一於簡潔性和易用性的改善,主要升級方向包括:數組
固然,若是你對 TensorFlow 1.x 原本就不熟悉,可能沒法看明白這些升級的內容。不用擔憂,本次課程將直接對 TensorFlow 2 進行學習,咱們再也不回首過去,直接展望將來。網絡
pip install -U tensorflow
接下來,咱們將從 TensorFlow 基礎概念語法入手,一步一步學習 TensorFlow 的使用。框架
首先,你應該知道什麼是向量和矩陣。咱們把 1 維的數組稱之爲向量, 2 維的數組稱之爲矩陣。那麼,如今告訴你張量其實表明着更大的範圍,你也能夠把其看做是N 維數組。函數
因此,若是如今從新描述向量和矩陣,就能夠是:一階張量爲向量,二階張量爲矩陣。固然,零階張量也就是標量,而更重要的是 N 階張量,也就是 N 維數組。工具
因此,張量並非什麼晦澀難懂的概念。若是不嚴謹的講,張量就是 NN 維數組。前面提到的向量、矩陣,也是張量。學習
後面將學習到的大多數深度學習框架都會使用張量的概念,這樣作的好處是統一對數據的定義。NumPy 中,數據都使用 Ndarray 多維數組進行定義,TensorFlow 中,數據都會用張量進行表述。優化
下面就來學習 TensorFlow 中對張量的定義。在 TensorFlow 中,每個 Tensor 都具有兩個基礎屬性:數據類型(默認:float32)和形狀。編碼
其中,數據類型大體以下表所示:spa
另外,TensorFlow 經過三種符號約定來描述張量維度:階,形狀和維數。三者之間的關係以下:
值得注意的是,上表中的示例都是形容張量的形狀。例如 [3, 4] 指的張量的形狀爲 [3, 4],而不是張量 [3, 4]。
根據不一樣的用途,TensorFlow 中主要有 2 種張量類型,分別是:
咱們能夠經過傳入列表或 NumPy 數組來新建變量和常量類型的張量:
代碼示例:
import tensorflow as tf tf.__version__
輸出
'2.0.0' v = tf.Variable([[1, 2], [3, 4]]) # 形狀爲 (2, 2) 的二維變量 v
輸出
<tf.Variable 'Variable:0' shape=(2, 2) dtype=int32, numpy= array([[1, 2], [3, 4]], dtype=int32)> c = tf.constant([[1, 2], [3, 4]]) # 形狀爲 (2, 2) 的二維常量 c
輸出
<tf.Tensor: id=9, shape=(2, 2), dtype=int32, numpy= array([[1, 2], [3, 4]], dtype=int32)>
仔細觀察,你會發現輸出包含了張量的 3 部分屬性,分別是形狀 shape,數據類型 dtype,以及對應的 NumPy 數組。
你還能夠直接經過 .numpy() 輸出張量的 NumPy 數組。
c.numpy()
輸出
array([[1, 2], [3, 4]], dtype=int32)
上面咱們已經介紹了常量張量,這裏再列舉幾個常常會用到的新建特殊常量張量的方法:
c = tf.zeros([3, 3]) # 3x3 全爲 0 的常量 Tensor c
輸出
<tf.Tensor: id=12, shape=(3, 3), dtype=float32, numpy= array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]], dtype=float32)> tf.ones_like(c) # 與 c 形狀一致全爲 1 的常量 Tensor
輸出
<tf.Tensor: id=15, shape=(3, 3), dtype=float32, numpy= array([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]], dtype=float32)> tf.fill([2, 3], 6) # 2x3 全爲 6 的常量 Tensor
輸出
<tf.Tensor: id=18, shape=(2, 3), dtype=int32, numpy= array([[6, 6, 6], [6, 6, 6]], dtype=int32)>
除此以外,咱們還能夠建立一些序列,例如:
tf.linspace(1.0, 10.0, 5, name="linspace")
輸出
<tf.Tensor: id=22, shape=(5,), dtype=float32, numpy=array([ 1\. , 3.25, 5.5 , 7.75, 10\. ], dtype=float32)> tf.range(start=1, limit=10, delta=2)
輸出
<tf.Tensor: id=26, shape=(5,), dtype=int32, numpy=array([1, 3, 5, 7, 9], dtype=int32)>
實際上,若是你熟悉 NumPy 的話,你會發現這與 NumPy 中建立各式各樣的多維數組方法大同小異。數據類型是一切的基礎,瞭解完張量咱們就能夠繼續學習張量的運算了。
TensorFlow 2 帶來的最大改變之一是將 1.x 的 Graph Execution(圖與會話機制)更改成 Eager Execution(動態圖機制)。在 1.x 版本中,低級別 TensorFlow API 首先須要定義數據流圖,而後再建立 TensorFlow 會話,這一點在 2.0 中被徹底捨棄。TensorFlow 2 中的 Eager Execution 是一種命令式編程環境,可當即評估操做,無需構建圖。
因此說,TensorFlow 的張量運算過程能夠像 NumPy 同樣直觀且天然了。接下來,咱們以最簡單的加法運算爲例:
c + c # 加法計算
輸出
<tf.Tensor: id=27, shape=(3, 3), dtype=float32, numpy= array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]], dtype=float32)>
若是你接觸過 1.x 版本的 TensorFlow,你要知道一個加法運算過程十分複雜。咱們須要初始化全局變量 → 創建會話 → 執行計算,最終才能打印出張量的運算結果。
init_op = tf.global_variables_initializer() # 初始化全局變量 with tf.Session() as sess: # 啓動會話 sess.run(init_op) print(sess.run(c + c)) # 執行計算
Eager Execution 帶來的好處顯而易見,其進一步下降了 TensorFlow 的入門門檻。以前的 Graph Execution 模式,實際上讓不少人在入門時都很鬱悶,由於徹底不符合正常思惟習慣。
TensorFlow 中提供的數學計算,包括線性代數計算方面的方法也是應有盡有,十分豐富。下面,咱們再列舉一個示例。
a = tf.constant([1., 2., 3., 4., 5., 6.], shape=[2, 3]) b = tf.constant([7., 8., 9., 10., 11., 12.], shape=[3, 2]) c = tf.linalg.matmul(a, b) # 矩陣乘法 c
輸出
<tf.Tensor: id=34, shape=(2, 2), dtype=float32, numpy= array([[ 58., 64.], [139., 154.]], dtype=float32)> tf.linalg.matrix_transpose(c) # 轉置矩陣
輸出
<tf.Tensor: id=36, shape=(2, 2), dtype=float32, numpy= array([[ 58., 139.], [ 64., 154.]], dtype=float32)>
你應該可以感受到,這些經常使用 API 都能在 NumPy 中找到對應的方法,這也就是課程須要你預先熟悉 NumPy 的緣由。因爲函數實在太多太多。通常來說,除了本身常用到的,都會在須要某種運算的時候,查閱官方文檔。
因此說,你能夠把 TensorFlow 理解成爲 TensorFlow 式的 NumPy + 爲搭建神經網絡而生的 API。
在數學中,微分是對函數的局部變化率的一種線性描述。雖然微分和導數是兩個不一樣的概念。可是,對一元函數來講,可微與可導是徹底等價的。若是你熟悉神經網絡的搭建過程,應該明白梯度的重要性。而對於複雜函數的微分過程是及其麻煩的,爲了提升應用效率,大部分深度學習框架都有自動微分機制。
TensorFlow 中,你可使用 tf.GradientTape 跟蹤所有運算過程,以便在必要的時候計算梯度。
w = tf.Variable([1.0]) # 新建張量 with tf.GradientTape() as tape: # 追蹤梯度 loss = w * w grad = tape.gradient(loss, w) # 計算梯度 grad
輸出
<tf.Tensor: id=52, shape=(1,), dtype=float32, numpy=array([2.], dtype=float32)>
上面,咱們演示了一個自動微分過程,它的數學求導過程以下:
因此,當 w 等於 1 時,計算結果爲 2。
tf.GradientTape 會像磁帶同樣記錄下計算圖中的梯度信息,而後使用 .gradient 便可回溯計算出任意梯度,這對於使用 TensorFlow 低階 API 構建神經網絡時更新參數很是重要。
上面,咱們已經學習了 TensorFlow 核心知識,接下來將對 TensorFlow API 中的經常使用模塊進行簡單的功能介紹。對於框架的使用,實際上就是靈活運用各類封裝好的類和函數。因爲 TensorFlow API 數量太多,迭代太快,因此你們要養成隨時 查閱官方文檔 的習慣。
在構建深度神經網絡時,TensorFlow 能夠說提供了你一切想要的組件,從不一樣形狀的張量、激活函數、神經網絡層,到優化器、數據集等,包羅萬象。因爲 TensorFlow 包含的接口太多,每一個都拿出來練習變得不切實際。關於TensorFlow 2.0 的基礎內容就到這裏!
想要了解新特性的詳細內容,請學習課程:
想要進行實戰項目,請學習課程: 《TensorFlow 2 深度學習入門與實踐》