您現在的位置是:首頁 > 美食首頁美食
全網最快掌握機器學習之深度學習之神經網路數學基礎(附原始碼)
什麼是標量和張量
1。全文簡介
要理解深度學習,需要熟悉很多簡單的數學概念:張量、張量運算、微分、梯度下降等。本文目的是用不那麼技術化的文字幫你建立對這些概念的直覺。特別地,我們將避免使用數學符號,因為數學符號可能會令沒有任何數學背景的人反感,而且對解釋問題也不是絕對必要的。
本文將首先給出一個神經網路的示例,引出張量和梯度下降的概念,然後逐個詳細介紹。請記住,這些概念對於理解後續文章中的示例至關重要。
讀完本文後,你會對神經網路的工作原理有一個直觀的理解,然後就可以學習神經網路的實際應用了(從下一篇開始)。
2。1 初識神經網路
我們來看一個具體的神經網路示例,使用 Python 的 Keras 庫來學習手寫數字分類。如果你沒用過 Keras 或類似的庫,可能無法立刻搞懂這個例子中的全部內容。甚至你可能還沒有安裝Keras。沒關係,下一章會詳細解釋這個例子中的每個步驟。因此,如果其中某些步驟看起來有些隨意,或者像魔法一樣,也請你不要擔心。下面我們要開始了。
我們這裡要解決的問題是,將手寫數字的灰度影象(28 畫素×28 畫素)劃分到 10 個類別中(0~9)。我們將使用 MNIST 資料集,它是機器學習領域的一個經典資料集,其歷史幾乎和這個領域一樣長,而且已被人們深入研究。這個資料集包含 60 000 張訓練影象和 10 000 張測試影象,由美國國家標準與技術研究院(National Institute of Standards and Technology,即 MNIST 中 的 NIST)在 20 世紀 80 年代收集得到。你可以將“解決”MNIST 問題看作深度學習的“Hello World”,正是用它來驗證你的演算法是否按預期執行。當你成為機器學習從業者後,會發現MNIST 一次又一次地出現在科學論文、部落格文章等中。圖 2-1 給出了 MNIST 資料集的一些樣本。
關於類和標籤的說明
在機器學習中,分類問題中的某個
類別
叫作
類
(class)。資料點叫作
樣本
(sample)。某個樣本對應的類叫作
標籤
(label)。
你不需要現在就嘗試在計算機上執行這個例子。但如果你想這麼做的話,首先需要安裝Keras,安裝方法見 3。3 節。
MNIST 資料集預先載入在 Keras 庫中,其中包括 4 個 Numpy 陣列。
from keras。datasets import mnist(train_images, train_labels), (test_images, test_labels) = mnist。load_data()
train_images 和 train_labels 組成了
訓練集
(training set),模型將從這些資料中進行學習。然後在
測試集
(test_set,即 test_images 和 test_labels)上對模型進行測試。
影象被編碼為 Numpy 陣列,而標籤是數字陣列,取值範圍為 0~9。影象和標籤一一對應。
我們來看一下訓練資料:
下面是測試資料:
接下來的工作流程如下:首先,將訓練資料(train_images 和 train_labels)輸入神經網路;其次,網路學習將影象和標籤關聯在一起;最後,網路對 test_images 生成預測,而我們將驗證這些預測與 test_labels 中的標籤是否匹配。
下面我們來構建網路。再說一遍,你現在不需要理解這個例子的全部內容。
神經網路的核心元件是
層
(layer),它是一種資料處理模組,你可以將它看成資料過濾器。
進去一些資料,出來的資料變得更加有用。具體來說,層從輸入資料中提取
表示
——我們期望這種表示有助於解決手頭的問題。大多數深度學習都是將簡單的層連結起來,從而實現漸進式的
資料蒸餾
(data distillation)。深度學習模型就像是資料處理的篩子,包含一系列越來越精細的資料過濾器(即層)。
本例中的網路包含 2 個 Dense 層,它們是密集連線(也叫
全連線
)的神經層。第二層(也是最後一層)是一個 10 路
softmax
層,它將返回一個由 10 個機率值(總和為 1)組成的陣列。每個機率值表示當前數字影象屬於 10 個數字類別中某一個的機率。
要想訓練網路,我們還需要選擇
編譯
(compile)步驟的三個引數。
‰
損失函式
(loss function):網路如何衡量在訓練資料上的效能,即網路如何朝著正確的方向前進。
‰
最佳化器
(optimizer):基於訓練資料和損失函式來更新網路的機制。
‰
在訓練和測試過程中需要監控的指標
(metric):本例只關心精度,即正確分類的影象所佔的比例。
後續兩章會詳細解釋損失函式和最佳化器的確切用途。
在開始訓練之前,我們將對資料進行預處理,將其變換為網路要求的形狀,並縮放到所有值都在 [0, 1] 區間。比如,之前訓練影象儲存在一個 uint8 型別的陣列中,其形狀為(60000, 28, 28),取值區間為 [0, 255]。我們需要將其變換為一個 float32 陣列,其形狀為 (60000, 28 * 28),取值範圍為 0~1。
我們還需要對標籤進行分類編碼,第 3 章將會對這一步驟進行解釋。
現在我們準備開始訓練網路,在 Keras 中這一步是透過呼叫網路的 fit 方法來完成的——我們在訓練資料上
擬合
(fit)模型。
訓練過程中顯示了兩個數字:一個是網路在訓練資料上的損失(loss),另一個是網路在訓練資料上的精度(acc)。
我們很快就在訓練資料上達到了 0。989(98。9%)的精度。現在我們來檢查一下模型在測試集上的效能。
測試集精度為 97。8%,比訓練集精度低不少。訓練精度和測試精度之間的這種差距是過擬合(overfit)造成的。過擬合是指機器學習模型在新資料上的效能往往比在訓練資料上要差,它是第 3 章的核心主題。
第一個例子到這裡就結束了。你剛剛看到了如何構建和訓練一個神經網路,用不到 20 行的Python 程式碼對手寫數字進行分類。下一章會詳細介紹這個例子中的每一個步驟,並講解其背後的原理。接下來你將要學到張量(輸入網路的資料儲存物件)、張量運算(層的組成要素)和梯度下降(可以讓網路從訓練樣本中進行學習)。
2。2 神經網路的資料表示
前面例子使用的資料儲存在多維 Numpy 陣列中,也叫
張量
(tensor)。一般來說,當前所有機器學習系統都使用張量作為基本資料結構。張量對這個領域非常重要,重要到 Google 的TensorFlow 都以它來命名。那麼什麼是張量?
張量這一概念的核心在於,它是一個數據容器。它包含的資料幾乎總是數值資料,因此它是數字的容器。你可能對矩陣很熟悉,它是二維張量。張量是矩陣向任意維度的推廣[注意,張量的維度(dimension)通常叫作
軸
(axis)]。
2。2。1 標量(0D 張量)
僅包含一個數字的張量叫作
標量
(scalar,也叫標量張量、零維張量、0D 張量)。在 Numpy中,一個 float32 或 float64 的數字就是一個標量張量(或標量陣列)。你可以用 ndim 屬性來檢視一個 Numpy 張量的軸的個數。標量張量有 0 個
軸
(ndim == 0)。張量軸的個數也叫作
階
(rank)。下面是一個 Numpy 標量。
2。2。2 向量(1D 張量)
數字組成的陣列叫作向量(vector)或一維張量(1D 張量)。一維張量只有一個軸。下面是一個 Numpy 向量。
>>> x = np。array([12, 3, 6, 14, 7])>>> xarray([12, 3, 6, 14, 7])>>> x。ndim
1
這個向量有 5 個元素,所以被稱為
5D 向量
。不要把 5D 向量和 5D 張量弄混! 5D 向量只有一個軸,沿著軸有 5 個維度,而 5D 張量有 5 個軸(沿著每個軸可能有任意個維度)。
維度
(dimensionality)可以表示沿著某個軸上的元素個數(比如 5D 向量),也可以表示張量中軸的個數(比如 5D 張量),這有時會令人感到混亂。對於後一種情況,技術上更準確的說法是
5 階張量
(張量的階數即軸的個數),但
5D 張量
這種模糊的寫法更常見
2。2。3 矩陣(2D 張量)
向量組成的陣列叫作矩陣(matrix)或二維張量(2D 張量)。矩陣有 2 個軸(通常叫作行和 列)。你可以將矩陣直觀地理解為數字組成的矩形網格。下面是一個 Numpy 矩陣。
>>> x = np。array([[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]])>>> x。ndim
2
第一個軸上的元素叫作行(row),第二個軸上的元素叫作列(column)。在上面的例子中,[5, 78, 2, 34, 0] 是 x 的第一行,[5, 6, 7] 是第一列。
2。2。4 3D 張量與更高維張量
將多個矩陣組合成一個新的陣列,可以得到一個 3D 張量,你可以將其直觀地理解為數字組成的立方體。下面是一個 Numpy 的 3D 張量。
>>> x = np。array([[[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]], [[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]], [[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]]])>>> x。ndim
3
將多個 3D 張量組合成一個數組,可以建立一個 4D 張量,以此類推。深度學習處理的一般是 0D 到 4D 的張量,但處理影片資料時可能會遇到 5D 張量。
2。2。5 關鍵屬性
張量是由以下三個關鍵屬性來定義的。
‰
軸的個數(階)
。例如,3D 張量有 3 個軸,矩陣有 2 個軸。這在 Numpy 等 Python 庫中 也叫張量的 ndim。
‰
形狀
。這是一個整數元組,表示張量沿每個軸的維度大小(元素個數)。例如,前面矩 陣示例的形狀為 (3, 5),3D 張量示例的形狀為 (3,3, 5)。向量的形狀只包含一個 元素,比如 (5,),而標量的形狀為空,即 ()。
‰
資料型別
(在 Python 庫中通常叫作> dtype)。這是張量中所包含資料的型別,例如,張 量的型別可以是 float32、uint8、float64 等。在極少數情況下,你可能會遇到字元 (char)張量。注意,Numpy(以及大多數其他庫)中不存在字串張量,因為張量儲存在預先分配的連續記憶體段中,而字串的長度是可變的,無法用這種方式儲存。
為了具體說明,我們回頭看一下 MNIST 例子中處理的資料。首先載入MNIST 資料集。
from keras。datasets import mnist(train_images, train_labels), (test_images, test_labels) = mnist。load_data()
接下來,我們給出張量 train_images 的軸的個數,即 ndim 屬性。
>>> print(train_images。ndim)
3
下面是它的形狀。
>>> print(train_images。shape)(60000, 28, 28)
下面是它的資料型別,即 dtype 屬性。
>>> print(train_images。dtype)uint8
所以,這裡 train_images 是一個由 8 位整陣列成的 3D 張量。更確切地說,它是 60 000個矩陣組成的陣列,每個矩陣由 28×28 個整陣列成。每個這樣的矩陣都是一張灰度影象,元素取值範圍為 0~255。
我們用 Matplotlib 庫(Python 標準科學套件的一部分)來顯示這個 3D 張量中的第 4 個數字,如圖 2-2 所示。
程式碼清單 2-6 顯示第 4 個數字
digit = train_images[4]import matplotlib。pyplot as pltplt。imshow(digit, cmap=plt。cm。binary)plt。show()