神經(jīng)網(wǎng)絡是機器學習領域中最強大、應用最廣泛的算法之一。乍一看,神經(jīng)網(wǎng)絡似乎是個黑盒子;輸入層將數(shù)據(jù)輸入到“隱藏層”中,經(jīng)過一個魔術之后,我們可以看到輸出層提供的信息。然而,理解隱藏層在做什么是神經(jīng)網(wǎng)絡實現(xiàn)和優(yōu)化的關鍵步驟。
在我們理解神經(jīng)網(wǎng)絡的道路上,我們將回答三個問題:
我們將要考慮的神經(jīng)網(wǎng)絡被嚴格地稱為人工神經(jīng)網(wǎng)絡,顧名思義,它是基于科學對人腦結構和功能的了解。
簡單地說,神經(jīng)網(wǎng)絡被定義為一種計算系統(tǒng),它由許多簡單但高度互聯(lián)的元素或節(jié)點組成,稱為“神經(jīng)元”,這些元素或節(jié)點被組織成層,利用外部輸入的動態(tài)狀態(tài)響應處理信息。在這種結構的上下文中,輸入層將模式引入到神經(jīng)網(wǎng)絡中,輸入層為輸入數(shù)據(jù)中出現(xiàn)的每個組件都有一個神經(jīng)元,并與網(wǎng)絡中出現(xiàn)的一個或多個隱藏層進行通信;之所以稱為“隱藏”,是因為它們不構成輸入或輸出層。在隱藏層中,所有的處理實際上都是通過一個以權重和偏差(通常稱為W和b)為特征的連接系統(tǒng)進行的:接收輸入,神經(jīng)元計算加權和添加偏差并根據(jù)結果和一個預設激活函數(shù)(最常見的一個是sigmoid,σ),它決定是否應該“fired”或激活。之后,神經(jīng)元將信息傳遞到下游的其他連接的神經(jīng)元,這個過程被稱為“forward pass”。在這個過程的最后,最后一個隱藏層被連接到輸出層,輸出層對于每個可能需要的輸出都有一個神經(jīng)元。
2層神經(jīng)網(wǎng)絡的基本結構
Wi:相應連接的權重。注意:計算網(wǎng)絡中存在的層數(shù)時,不包括輸入層。
現(xiàn)在我們已經(jīng)了解了神經(jīng)網(wǎng)絡基本結構的外觀,我們將繼續(xù)解釋它是如何工作的。為了做到這一點,我們需要解釋我們可以包含在網(wǎng)絡中的不同類型的神經(jīng)元。
我們要解釋的第一種神經(jīng)元是Perceptron。即使它的使用已經(jīng)在今天衰退,了解它們如何工作將為我們提供關于更多現(xiàn)代神經(jīng)元如何運作的良好線索。
感知器使用函數(shù)通過將二進制變量的矢量映射到單個二進制輸出來學習二元分類器,并且它還可以用于監(jiān)督學習。在這種情況下,感知器遵循以下步驟:
我們也可以把感知器函數(shù)寫成這樣:
注意:b是偏差,相當于-threshold,wx是w的點積,是矢量,其中分量是權重,x是由輸入組成的矢量。
該算法最突出的一點是,我們可以改變權重和偏差,以獲得不同的決策模型。我們可以給這些輸入賦予更多的權重,這樣如果它們是正的,就會有利于我們想要的輸出。另外,因為偏差可以理解為輸出1的難易程度的度量,如果我們想讓期望的輸出或多或少發(fā)生,我們可以降低或提高它的值。如果我們注意這個公式,我們可以觀察到一個大的正向偏差會使輸出1變得非常容易;然而,負的偏見將使輸出1的任務變得非常不可能。
因此,感知器可以分析不同的數(shù)據(jù),并根據(jù)設定的偏好做出決定。事實上,創(chuàng)建更復雜的網(wǎng)絡是有可能的,包括更多的感知器層,每一層都取前一層的輸出并加權,做出越來越復雜的決定。
如果感知器能很好地做出復雜的決定,為什么我們還需要其他類型的神經(jīng)元呢?包含感知器的網(wǎng)絡的一個缺點是,甚至在只有一個感知器中,權重或偏壓的小變化,也會嚴重地改變從0到1的輸出,反之亦然。我們真正想要的是通過引入權重或偏差的小修改來逐漸改變我們網(wǎng)絡的行為。這就是一種更現(xiàn)代的神經(jīng)元派上用場的地方:Sigmoid神經(jīng)元。Sigmoid neurons和感知器的主要區(qū)別在于輸入和輸出可以是0到1之間的任意連續(xù)值。在考慮權重w和偏差b的情況下,將sigmoid函數(shù)應用到輸入中,得到輸出結果。為了更直觀的理解,我們可以這樣寫:
所以,輸出的公式是:
如果我們對這個函數(shù)進行數(shù)學分析,我們可以得到我們的函數(shù)σ 的圖形,如下所示,并得出結論:當z很大且正數(shù)時,函數(shù)達到其最大漸近值1; 但是,如果z很大且為負,則函數(shù)達到其最小漸近值0.這里是sigmoid函數(shù)變得非常有趣的地方,因為它具有中等的z值,函數(shù)采用平滑且接近線性的形狀。在此間隔中,權重(Δwj)或偏差(Δbj)的微小變化將在輸出中產(chǎn)生微小變化; 我們所期待的行為是感知器的改進。
我們知道一個函數(shù)的導數(shù)是y值相對于變量x的變化速率的度量,在這種情況下,變量y是我們的輸出變量x是權重和偏差的函數(shù)。我們可以利用這一點,用導數(shù)來計算輸出的變化,特別是偏導數(shù)(關于w和關于b的)。在sigmoid函數(shù)中,導數(shù)將被縮減為計算:f(z)*(1-f(z))。
這里有一個簡單的Python代碼,可以用來建模一個sigmoid函數(shù):
'''Build a sigmoid function to map any value to a value between zero and one\n',Refers to case of logistic function defined by: s(z) = 1/(1+e^-z)which derivative is bell shape. derivative is equal to f(z)*(1-f(z))'''def sigmoid(x, deriv = False): if deriv == True: return x*(1-x) return 1/(1+np.exp(-x))
我們剛剛解釋了我們網(wǎng)絡中每個神經(jīng)元的功能,現(xiàn)在,我們可以檢查其余神經(jīng)元是如何工作的。將來自一層的輸出用作下一層的輸入的神經(jīng)網(wǎng)絡稱為前饋,特別是因為不涉及循環(huán)并且信息僅pass forward而從不返回。
假設我們有一個訓練集,我們想要使用一個3層神經(jīng)網(wǎng)絡,我們也使用上面看到的sigmoid神經(jīng)??元來預測某個特征。根據(jù)我們對神經(jīng)網(wǎng)絡結構的解釋,需要首先將權重和偏差分配給一層??中的神經(jīng)元與下一層中的神經(jīng)元之間的連接。通常,偏差和權重都在突觸矩陣中隨機初始化。如果我們在python中編碼神經(jīng)網(wǎng)絡,我們可以使用Numpy函數(shù)np.random.random 生成高斯分布(其中均值等于0,標準差為1)。
之后,我們將從前饋步驟開始構建神經(jīng)網(wǎng)絡,以計算預測輸出; 換句話說,我們只需要構建網(wǎng)絡中涉及的不同層:
我們還需要迭代訓練集以讓網(wǎng)絡學習。為此,我們將添加for 循環(huán)。
#For loop iterate over the training setfor i in range(60000): #First layer is the input layer0 = X #Second layer can be obtained with the multiplication of each layer #and its synapsis and then running sigmoid function layer1 = sigmoid(np.dot(layer0, syn0)) #Do the same with l1 and its synapsis layer2 = sigmoid(np.dot(layer1,syn1))
到目前為止,我們已經(jīng)創(chuàng)建了神經(jīng)網(wǎng)絡的基本結構:不同的層,神經(jīng)元之間連接的權重和偏差,以及sigmoid 函數(shù)。但這些都沒有解釋神經(jīng)網(wǎng)絡如何在預測數(shù)據(jù)集中的模式方面做得如此出色。這就是我們最后一個問題。
機器學習算法的主要優(yōu)勢在于它們每次預測輸出時都能學習和改進。但他們能學到什么意味著什么呢?在神經(jīng)網(wǎng)絡的背景下,它意味著定義神經(jīng)元之間連接的權重和偏差變得更加精確; 最后,選擇權重和偏差,例如來自網(wǎng)絡的輸出近似于所有訓練輸入的實際值y(x)。
那么,為了讓我們知道是否需要繼續(xù)尋找更精確的參數(shù),我們如何量化我們的預測與實際值的距離?為了這個目標,我們需要計算一個誤差,或者換句話說,定義一個成本函數(shù)(成本函數(shù)不是預測網(wǎng)絡正確輸出的誤差;換句話說,這就是預期和預期輸出的差值)。在神經(jīng)網(wǎng)絡中,最常用的是二次成本函數(shù),也稱為均方誤差,公式定義為:
w和b分別表示網(wǎng)絡中的所有權重和偏差。n是訓練輸入的總數(shù)。a是輸出,而x是輸入。Σ是所有訓練輸入的總和。
該函數(shù)優(yōu)于線性誤差,因為在神經(jīng)網(wǎng)絡中,權重和偏差的微小變化不會使正確輸出的數(shù)量發(fā)生任何變化; 因此,使用二次函數(shù),其中較大的差值對成本函數(shù)的影響比小的差異更有助于確定如何修改這些參數(shù)。
另一方面,我們可以看到,對于所有訓練輸入,我們的成本函數(shù)隨著輸出更接近實際值y而變小。我們算法的主要目標是通過找到一組權重和偏差來使這個成本函數(shù)最小化,以使其盡可能小。實現(xiàn)這一目標的主要工具是一種名為Gradient Descent的算法。
那么,我們應該回答的下一個問題是如何最大限度地降低成本函數(shù)。從微積分中,我們知道函數(shù)可以具有全局最大值和/或最小值,即函數(shù)實現(xiàn)其可以具有的最大值或最小值。我們也知道獲得這一點的一種方法是計算導數(shù)。但是,當我們有一個帶有兩個變量的函數(shù)時,很容易計算,但在神經(jīng)網(wǎng)絡的情況下,它們包含許多變量,這使得這個計算很難完成。
讓我們看一下隨機函數(shù),如下圖:
我們可以看到這個函數(shù)具有全局最小值。正如我們之前所說,我們可以計算導數(shù)以計算最小值的位置,或者我們可以采用另一種方法。我們可以從一個隨機點開始嘗試沿箭頭方向做一個小的移動,我們在數(shù)學上說,在x方向上移動Δx,在y方向上移動Δy,并計算我們的函數(shù)ΔC的變化。因為方向的變化率是函數(shù)的導數(shù),我們可以將函數(shù)的變化表示為:
在這里,我們將從函數(shù)梯度的微積分中定義:
函數(shù)的梯度:具有偏導數(shù)的向量
現(xiàn)在,我們可以將函數(shù)中的更改重寫為:
C的梯度將函數(shù)C的變化與(x,y)的變化聯(lián)系起來
現(xiàn)在,我們可以看到當我們選擇參數(shù)的某個變化時,成本函數(shù)會發(fā)生什么。我們選擇向任何方向移動的數(shù)量稱為學習率,它定義了我們向全局最小化移動的速度。如果我們選擇一個非常小的數(shù)字,我們需要做出太多的動作來達到這一點; 但是,如果我們選擇一個非常大的數(shù)字,我們就有可能超越這一點而永遠無法達到它。所以挑戰(zhàn)在于選擇足夠小的學習率。選擇學習率后,我們可以更新我們的權重和偏見,并采取另一種行動; 我們在每次迭代中重復的過程。
因此,簡而言之,梯度下降通過重復計算梯度?C,然后更新權重和偏差,并試圖找到最小化值來實現(xiàn)。這就是神經(jīng)網(wǎng)絡學習的方式。
有時候,計算梯度可能非常復雜。然而,有一種方法可以加速這種計算,叫做隨機梯度下降法。這是通過估算梯度?C通過計算梯度而不是隨機選擇的小樣本訓練的輸入。然后,將這些小樣本平均起來,就能很好地估計出真實的梯度,加速梯度下降,從而學習得更快。
但是我們如何計算成本函數(shù)的梯度呢?這是另一個算法的地方:反向傳播。該算法的目標是計算關于任何權重w和任何偏差b的成本函數(shù)的偏導數(shù);實際上,這意味著計算從最終層開始的誤差矢量,然后將其傳播回以更新權重和偏差。我們需要回去的原因是成本是網(wǎng)絡輸出的函數(shù)。我們可以觀察公式。
反向傳播算法給出的四個基本公式,可用于實現(xiàn)神經(jīng)網(wǎng)絡
反向傳播算法僅針對一個訓練示例計算成本函數(shù)的梯度。因此,我們需要將反向傳播與學習算法相結合,例如隨機梯度下降,以便計算所有訓練集的梯度。
現(xiàn)在,我們如何將它應用于python中的神經(jīng)網(wǎng)絡?在這里,我們可以逐步看到計算結果:
現(xiàn)在我們可以將我們在算法方面看到的所有這些公式和概念放在一起,看看我們如何實現(xiàn)的:
當然,還有更多的概念、實現(xiàn)和改進,可以對神經(jīng)網(wǎng)絡進行改進,這些神經(jīng)網(wǎng)絡已經(jīng)在過去的幾年里越來越廣泛地被使用。但我希望本文能告訴你什么是神經(jīng)網(wǎng)絡,它是如何工作的,以及它是如何利用梯度下降和反向傳播學習的。