【深度】解析深度神經網絡背後的數學原理


新智元推薦

來源:AI科技大本營(ID:rgznai100)

作者:Piotr Skalski

譯者:巧克力 編輯:Jane

【新智元導讀】爲了更好地理解神經網絡的運作,今天只爲大家解讀神經網絡背後的數學原理。而作者寫這篇文章的目的一是爲了整理自己學到的知識;二是希望這篇文章可以有助於大家的學習與理解。對於代數和微積分相關內容基礎薄弱的小夥伴們,雖然文中涉及不少數學知識,但我會盡量讓內容易於理解。

解析深度網絡背後的數學

如今,已有許多像 Keras, TensorFlow, PyTorch 這樣高水平的專門的庫和框架,我們就不用總擔心矩陣的權重太多,或是對使用的激活函數求導時存儲計算的規模太大這些問題了。基於這些框架,我們在構建一個神經網絡時,甚至是一個有着非常複雜的結構的網絡時,也僅需少量的輸入和代碼就足夠了,極大地提高了效率。無論如何,神經網絡背後的原理方法對於像架構選擇、超參數調整或者優化這樣的任務有着很大的幫助。

圖一 訓練集可視化

舉個例子,我們將利用上圖展示的訓練集數據去解決一個二分類問題。從上面的圖可以看出,數據點形成了兩個圓,這對於許多傳統的機器學習算法是不容易的,但是現在用一個小的神經網絡就可能很好地解決這個問題了。爲了解決這個問題,我們將構建一個神經網絡:包括五個全連接層,每層都含有不同數目的單元,結構如下:

圖二 神經網絡架構

其中,隱藏層使用 ReLU 作爲激活函數,輸出層使用 Sigmoid。這是一個非常簡單的架構,但是對於解決並解釋這個問題已經足夠了。

用 KERAS 求解

首先,先給大家介紹一個解決方法,使用了一個最受歡迎的機器學習庫—— KERAS 。

from keras.models import Sequential

from keras.layers import Dense



model = Sequential()

model.add(Dense(4, input_dim=2,activation='relu'))

model.add(Dense(6, activation='relu'))

model.add(Dense(6, activation='relu'))

model.add(Dense(4, activation='relu'))

model.add(Dense(1, activation='sigmoid'))



model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

model.fit(X_train, y_train, epochs=50, verbose=0)

正如我在簡介中提到的,少量的輸入數據和代碼就足以構建和訓練出一個模型,並且在測試集上的分類精度幾乎達到 100%。概括來講,我們的任務其實就是提供與所選架構一致的超參數(層數、每層的神經元數、激活函數或者迭代次數)。先給大家展示一個超酷的可視化結果,是我在訓練過程中得到的:

圖三 訓練中正確分類區域的可視化

現在我們來解析這背後的原理。

什麼是神經網絡?

讓我們從關鍵問題開始:什麼是神經網絡?它是一種由生物啓發的,用來構建可以學習並且獨立解釋數據中聯繫的計算機程序的方法。如上圖二所示,網絡就是各層神經元的集合,這些神經元排列成列,並且相互之間連接,可以進行交流。

單個神經元

每個神經元以一組 x 變量(取值從 1 到 n )的值作爲輸入,計算預測的 y-hat 值。假設訓練集中含有 m 個樣本,則向量 x 表示其中一個樣本的各個特徵的取值。此外,每個單元有自己的參數集需要學習,包括權重向量和偏差,分別用 w 和 b 表示。在每次迭代中,神經元基於本輪的權重向量計算向量 x 的加權平均值,再加上偏差。最後,將計算結果代入一個非線性激活函數 g。我會在下文中介紹一些最流行的激活函數。

圖四 單個神經元

單層

現在我們看一下神經網絡中整體的一層是怎麼計算的。我們將整合每個單元中的計算,進行向量化,然後寫成矩陣的形式。爲了統一符號,我們選取第 l 層寫出矩陣等式,下標 i 表示第 i 個神經元。

圖五 單層神經網絡

注意一點:當我們對單個單元寫方程的時候,用到了 x 和 y-hat,它們分別表示特徵列向量和預測值。但當我們對整個層寫的時候,要用向量 a 表示相應層的激活值。因此, 向量 x 可以看做第 0 層輸入層的激活值。每層的各個神經元相似地滿足如下等式:

爲了清楚起見,以下是第二層的所有表達式:

可見,每層的表達式都是相似的。用 for 循環來表示很低效,因此爲了加速計算速度我們使用了向量化。首先,將權重向量 w 的轉置堆疊成矩陣 W。相似地,將各個神經元的偏差也堆在一起組成列向量 b。由此,我們就可以很輕鬆地寫出一個矩陣等式來表示關於某一層的所有神經元的計算。使用的矩陣和向量維數表示如下:

多樣本向量化

到目前爲止,我們寫出的等式僅包含一個樣本。但在神經網絡的學習過程中,通常會處理一個龐大的數據集,可達百萬級的輸入。因此,下一步需要進行多樣本向量化。我們假設數據集中含有 m 個輸入,每個輸入有 nx 個特徵。首先,將每層的列向量 x, a, z 分別堆成矩陣 X, A, Z。然後,根據新的矩陣重寫之前的等式。

什麼是激活函數?我們爲什麼需要它?

激活函數是神經網絡的關鍵元素之一。沒有它們,神經網絡就只是一些線性函數的組合,其本身也只能是一個線性函數。我們的模型有複雜度的限制,不能超過邏輯迴歸。其中,非線性元保證了更好的適應性,並且能在學習過程中提供一些複雜的函數。激活函數對學習的速度也有顯著影響,這也是在選擇時的評判標準之一。圖六展示了一些常用的激活函數。近年來,隱藏層中使用最廣的激活函數大概就是 ReLU 了。不過,當我們在做二進制分類問題時,我們有時仍然用 sigmoid,尤其是在輸出層中,我們希望模型返回的值在 0 到 1 之間。

圖六 常用激活函數及其導數函數圖像

損失函數

關於學習過程進展的基本的信息來源就是損失函數值了。通常來說,損失函數可以表示我們離 “理想” 值還差多遠。在本例中,我們用 binary crossentropy(兩元交叉熵)來作爲損失函數,不過還有其他的損失函數,需要具體問題具體分析。兩元交叉熵函數表示如下:

下圖展示了在訓練過程中其值的變化,可見其值隨着迭代次數如何增加與減少,精度如何提高

圖七 訓練過程中精確度及損失的變化

神經網絡如何學習?

學習過程其實就是在不斷地更新參數 W 和 b 的值從而使損失函數最小化。爲此,我們運用微積分以及梯度下降的方法來求函數的極小。在每次迭代中,我們將分別計算損失函數對神經網絡中的每個參數的偏導數值。對這方面計算不太熟悉的小夥伴,我簡單解釋一下,導數可以刻畫函數的(斜率)。我們已經知道了怎樣迭代變量會有怎麼樣的變化,爲了對梯度下降有更直觀的認識,我展示了一個可視化動圖,從中可以看到我們是怎麼通過一步步連續的迭代逼近極小值的。在神經網絡中也是一樣的——每一輪迭代所計算的梯度顯示我們應該移動的方向。而他們間最主要的差別在於,神經網絡需要計算更多的參數。確切地說,怎麼計算如此複雜的導數呢?

圖八 動態梯度下降

反向傳播算法

反向傳播算法是一種可以計算十分複雜的梯度的算法。在神經網絡中,各參數的調整公式如下:

其中,超參數 α 表示學習率,用以控制更新步長。選定學習率是非常重要的——太小,NN 學習得太慢;太大,無法達到極小點。用鏈式法則計算 dW 和 db —— 損失函數對 W 和 b 的偏導數, dW 和 db 的維數與 W 和 b 相等。圖九展示了神經網絡中的一系列求導操作,從中可以清楚地看到前向和後向傳播是怎樣共同優化損失函數的。

圖九 前向與後向傳播

結論

希望這篇文章對各位小夥伴理解神經網絡內部運用的數學原理有所幫助。當我們使用神經網絡時,理解這個過程的基本原理是很有幫助的。文中講述的內容雖然只是冰山一角,但都是我認爲最重要的知識點。因此,我強烈建議大家能試着獨立地去編一個小的神經網絡,不要依賴框架,僅僅只用 Numpy 嘗試一下。

原文鏈接: https://towardsdatascience.com/https-medium-com-piotr-skalski92-deep-dive-into-deep-networks-math-17660bc376ba

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