本文目錄一覽:
一文搞懂梯度下降&反向傳播
如果把神經網絡模型比作一個黑箱,把模型參數比作黑箱上面一個個小旋鈕,那麼根據通用近似理論(universal approximation theorem),只要黑箱上的旋鈕數量足夠多,而且每個旋鈕都被調節到合適的位置,那這個模型就可以實現近乎任意功能(可以逼近任意的數學模型)。
顯然,這些旋鈕(參數)不是由人工調節的,所謂的機器學習,就是通過程序來自動調節這些參數。神經網絡不僅參數眾多(少則十幾萬,多則上億),而且網絡是由線性層和非線性層交替疊加而成,上層參數的變化會對下層的輸出產生非線性的影響,因此,早期的神經網絡流派一度無法往多層方向發展,因為他們找不到能用於任意多層網絡的、簡潔的自動調節參數的方法。
直到上世紀80年代,祖師爺辛頓發明了反向傳播算法,用輸出誤差的均方差(就是loss值)一層一層遞進地反饋到各層神經網絡,用梯度下降法來調節每層網絡的參數。至此,神經網絡才得以開始它的深度之旅。
本文用python自己動手實現梯度下降和反向傳播算法。 請點擊這裡 到Github上查看源碼。
梯度下降法是一種將輸出誤差反饋到神經網絡並自動調節參數的方法,它通過計算輸出誤差的loss值( J )對參數 W 的導數,並沿着導數的反方向來調節 W ,經過多次這樣的操作,就能將輸出誤差減小到最小值,即曲線的最低點。
雖然Tensorflow、Pytorch這些框架都實現了自動求導的功能,但為了徹底理解參數調節的過程,還是有必要自己動手實現梯度下降和反向傳播算法。我相信你和我一樣,已經忘了之前學的微積分知識,因此,到可汗學院複習下 Calculus
和 Multivariable Calculus 是個不錯的方法,或是拜讀 這篇關於神經網絡矩陣微積分的文章 。
Figure2是求導的基本公式,其中最重要的是 Chain Rule ,它通過引入中間變量,將“ y 對 x 求導”的過程轉換為“ y 對中間變量 u 求導,再乘以 u 對 x 求導”,這樣就將一個複雜的函數鏈求導簡化為多個簡單函數求導。
如果你不想涉及這些求導的細節,可以跳過具體的計算,領會其思想就好。
對於神經網絡模型: Linear – ReLu – Linear – MSE(Loss function) 來說,反向傳播就是根據鏈式法則對 求導,用輸出誤差的均方差(MSE)對模型的輸出求導,並將導數傳回上一層神經網絡,用於它們來對 w 、 b 和 x (上上層的輸出)求導,再將 x 的導數傳回到它的上一層神經網絡,由此將輸出誤差的均方差通過遞進的方式反饋到各神經網絡層。
對於 求導的第一步是為這個函數鏈引入中間變量:
接着第二步是對各中間變量求導,最後才是將這些導數乘起來。
首先,反向傳播的起點是對loss function求導,即 。 :
mse_grad()之所以用unsqueeze(-1)給導數增加一個維度,是為了讓導數的shape和tensor shape保持一致。
linear層的反向傳播是對 求導,它也是一個函數鏈,也要先對中間變量求導再將所有導數相乘:
這些中間變量的導數分別是:
對向量 求導,指的是對向量所有的標量求偏導( ),即: ,這個橫向量也稱為y的梯度。
這裡 ,是一個向量,因此, 求導,指的是y的所有標量(y_1, y_2, …, y_n)對向量x求偏導,即:
。
這個矩陣稱為雅克比矩陣,它是個對角矩陣,因為 ,因此 。
同理, 。
因此,所有中間導數相乘的結果:
lin_grad() 中的inp.g、w.g和b.g分別是求 的導數,以inp.g為例,它等於 ,且需要乘以前面各層的導數,即 outp.g @ w.t() ,之所以要用點積運算符(@)而不是標量相乘,是為了讓它的導數shape和tensor shape保持一致。同理,w.g和b.g也是根據相同邏輯來計算的。
ReLu層的求導相對來說就簡單多了,當輸入 = 0時,導數為0,當輸入 0時,導數為1。
求導運算終於結束了,接下來就是驗證我們的反向傳播是否正確。驗證方法是將forward_backward()計算的導數和Pytorch自動微分得到的導數相比較,如果它們相近,就認為我們的反向傳播算法是正確的。
首先,將計算好的參數導數保存到w1g、b1g、w2g和b2g中,再用Pytorch的自動微分來求w11、b11、w22和b22的導數。
最後,用np.allclose()來比較導數間的差異,如果有任何一個導數不相近,assert就會報錯。結果證明,我們自己動手實現的算法是正確的。
反向傳播是遵循鏈式法則的,它將前向傳播的輸出作為輸入,輸入作為輸出,通過遞進的方式將求導這個動作從後向前傳遞迴各層。神經網絡參數的求導需要進行矩陣微積分計算,根據這些導數的反方向來調節參數,就可以讓模型的輸出誤差的優化到最小值。
歡迎關注和點贊,你的鼓勵將是我創作的動力
從零開始用Python構建神經網絡
從零開始用Python構建神經網絡
動機:為了更加深入的理解深度學習,我們將使用 python 語言從頭搭建一個神經網絡,而不是使用像 Tensorflow 那樣的封裝好的框架。我認為理解神經網絡的內部工作原理,對數據科學家來說至關重要。
這篇文章的內容是我的所學,希望也能對你有所幫助。
神經網絡是什麼?
介紹神經網絡的文章大多數都會將它和大腦進行類比。如果你沒有深入研究過大腦與神經網絡的類比,那麼將神經網絡解釋為一種將給定輸入映射為期望輸出的數學關係會更容易理解。
神經網絡包括以下組成部分
? 一個輸入層,x
? 任意數量的隱藏層
? 一個輸出層,?
? 每層之間有一組權值和偏置,W and b
? 為隱藏層選擇一種激活函數,σ。在教程中我們使用 Sigmoid 激活函數
下圖展示了 2 層神經網絡的結構(注意:我們在計算網絡層數時通常排除輸入層)
2 層神經網絡的結構
用 Python 可以很容易的構建神經網絡類
訓練神經網絡
這個網絡的輸出 ? 為:
你可能會注意到,在上面的等式中,輸出 ? 是 W 和 b 函數。
因此 W 和 b 的值影響預測的準確率. 所以根據輸入數據對 W 和 b 調優的過程就被成為訓練神經網絡。
每步訓練迭代包含以下兩個部分:
? 計算預測結果 ?,這一步稱為前向傳播
? 更新 W 和 b,,這一步成為反向傳播
下面的順序圖展示了這個過程:
前向傳播
正如我們在上圖中看到的,前向傳播只是簡單的計算。對於一個基本的 2 層網絡來說,它的輸出是這樣的:
我們在 NeuralNetwork 類中增加一個計算前向傳播的函數。為了簡單起見我們假設偏置 b 為0:
但是我們還需要一個方法來評估預測結果的好壞(即預測值和真實值的誤差)。這就要用到損失函數。
損失函數
常用的損失函數有很多種,根據模型的需求來選擇。在本教程中,我們使用誤差平方和作為損失函數。
誤差平方和是求每個預測值和真實值之間的誤差再求和,這個誤差是他們的差值求平方以便我們觀察誤差的絕對值。
訓練的目標是找到一組 W 和 b,使得損失函數最好小,也即預測值和真實值之間的距離最小。
反向傳播
我們已經度量出了預測的誤差(損失),現在需要找到一種方法來傳播誤差,並以此更新權值和偏置。
為了知道如何適當的調整權值和偏置,我們需要知道損失函數對權值 W 和偏置 b 的導數。
回想微積分中的概念,函數的導數就是函數的斜率。
梯度下降法
如果我們已經求出了導數,我們就可以通過增加或減少導數值來更新權值 W 和偏置 b(參考上圖)。這種方式被稱為梯度下降法。
但是我們不能直接計算損失函數對權值和偏置的導數,因為在損失函數的等式中並沒有顯式的包含他們。因此,我們需要運用鏈式求導發在來幫助計算導數。
鏈式法則用於計算損失函數對 W 和 b 的導數。注意,為了簡單起見。我們只展示了假設網絡只有 1 層的偏導數。
這雖然很簡陋,但是我們依然能得到想要的結果—損失函數對權值 W 的導數(斜率),因此我們可以相應的調整權值。
現在我們將反向傳播算法的函數添加到 Python 代碼中
為了更深入的理解微積分原理和反向傳播中的鏈式求導法則,我強烈推薦 3Blue1Brown 的如下教程:
Youtube:
整合併完成一個實例
既然我們已經有了包括前向傳播和反向傳播的完整 Python 代碼,那麼就將其應用到一個例子上看看它是如何工作的吧。
神經網絡可以通過學習得到函數的權重。而我們僅靠觀察是不太可能得到函數的權重的。
讓我們訓練神經網絡進行 1500 次迭代,看看會發生什麼。 注意觀察下面每次迭代的損失函數,我們可以清楚地看到損失函數單調遞減到最小值。這與我們之前介紹的梯度下降法一致。
讓我們看看經過 1500 次迭代後的神經網絡的最終預測結果:
經過 1500 次迭代訓練後的預測結果
我們成功了!我們應用前向和方向傳播算法成功的訓練了神經網絡並且預測結果收斂於真實值。
注意預測值和真實值之間存在細微的誤差是允許的。這樣可以防止模型過擬合併且使得神經網絡對於未知數據有着更強的泛化能力。
下一步是什麼?
幸運的是我們的學習之旅還沒有結束,仍然有很多關於神經網絡和深度學習的內容需要學習。例如:
? 除了 Sigmoid 以外,還可以用哪些激活函數
? 在訓練網絡的時候應用學習率
? 在面對圖像分類任務的時候使用卷積神經網絡
我很快會寫更多關於這個主題的內容,敬請期待!
最後的想法
我自己也從零開始寫了很多神經網絡的代碼
雖然可以使用諸如 Tensorflow 和 Keras 這樣的深度學習框架方便的搭建深層網絡而不需要完全理解其內部工作原理。但是我覺得對於有追求的數據科學家來說,理解內部原理是非常有益的。
這種練習對我自己來說已成成為重要的時間投入,希望也能對你有所幫助
如何用Python/NumPy實現反向傳播How 來自愛可可
魏曹睿後期,政治開始衰落。曹睿下令拆承露盤更是天人共怒。遼東公孫淵起兵造反,司馬懿出兵剿滅。曹睿病危,將曹芳託付於司馬懿而病逝。曹睿死後,司馬懿詐病賺曹爽,奪了曹爽的兵權。魏嘉平三年(公元251年)司馬懿病逝,其子司馬師、司馬昭獨攬朝政,魏國名存實亡,大權盡歸司馬氏之手。後高貴鄉公曹髦在位,司馬師病故。曹髦因對司馬昭由懼到恨,驅車率眾臣與司馬昭決鬥,反被司馬昭殺死。[1] 漢將姜維繼承諸葛亮遺志,出兵伐魏,與魏將鄧艾對戰。前後九次,交戰中雙方互有勝敗,姜維亦曾經將司馬昭困於鐵籠山,因山泉突涌而未能困死。然而最終姜維沒有取得任何顯著成果。朝廷里,諸葛亮死後,漢帝劉禪更加接近宦官,不理朝政,國勢日趨衰危。此間吳帝孫權病逝,其後的孫亮、孫休為孫峻、孫綝所控制,吳宮內多次發生干戈。孫休竟險些喪於孫~之手,幸得老將丁奉相救。丁奉死後,東吳更加衰敗。[1]
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/244581.html