自己动手从零搭建神经网络
簡書博客地址:https://www.jianshu.com/p/388bbb5e0245
入門
首先,先簡單的講解一下神經網絡。
我們從構建超級簡單的機器開始。有一臺基本的機器,接受了一個問題,做了一些“思考”,并輸出了一個答案。就像我們從眼睛輸入圖片,使用大腦分析場景,并得出在場景中有哪些物體的結論。
試想一下將千米轉化為英里的一臺機器,如下圖所示。我們所知道的就是,兩者之間的關系是線性的。這意味著,如果英里數加倍,那么表示相同距離的千米數也是加倍的。千米和英里之間的這種線性關系,為我們提供了這種神秘計算的線索,即它的形式應該是“英里=千米×C”,其中C為常數。現在,我們還不知道這個常數C是多少。
首先,我們從嘗試使用C=0.5,帶入機器計算出結果。
結果比實際值少了12.137。這是計算結果與我們列出的示例真實值之間的差值,是誤差。即:
誤差值=真實值-計算值
=62.137-50
=12.137
讓我們將C從0.5稍微增加到0.6,再次進行計算。
現在,由于將C設置為0.6,我們得到了英里=千米×C=100×0.6=60,這個答案比先前50的答案更好。我們取得了明顯的進步。
讓我們再次重復這個過程。輸出值60還是太小了。我們再次微調C,將其從0.6調到0.7。結果超過了已知的正確答案。先前的誤差值為2.137,現在的誤差值為-7.863。我們為什么不使用一個較小的量,微調C,將C從0.6調到0.61呢?

這比先前得到的答案要好得多。我們得到輸出值61,比起正確答案62.137,這只差了1.137。
因此,最后的這次嘗試告訴我們,應該適度調整C值。如果輸出值越來越接近正確答案,即誤差值越來越小,那么我們就不要做那么大的調整。使用這種方式,我們就可以避免像先前那樣得到超調的結果。
再換個例子,簡單分析一下,比如我們希望訓練線性分類器,使其能夠正確分類瓢蟲或毛蟲。下圖并不能準確的區分瓢蟲和毛蟲。
我們嘗試修改直線的斜率,這樣我們就可以精確的區分出這兩種小蟲。那如何使用公式進行表達呢?
回顧一下,在千米轉換為英里預測器的實例中,我們有一個調整了參數的線性函數。此處,由于分界線是一條直線,因此我們也可以進行相同的處理:
y=Ax
由于嚴格來說,此處的直線不是一臺預測器,因此我們有意使用名稱y和x,而不使用名稱長度和寬度。與先前我們將千米轉換為英里不一樣,這條直線不將寬度轉換為長度。相反,它是一條分界線,是一臺分類器。
同樣,我們也可以采用之前的方法,根據誤差來對直線進行調整,對此不再贅述。
神經網絡介紹
前面簡單的介紹了線性分類器,下面開始正式介紹神經網絡。神經網絡是機器學習中的一種模型,是一種模仿動物神經網絡行為特征,進行分布式并行信息處理的算法數學模型。這種網絡依靠系統的復雜程度,通過調整內部大量節點之間相互連接的關系,從而達到處理信息的目的。下圖就是一個簡單的神經網絡。
神經元
神經元是神經網絡中最基本的結構,也可以說是神經網絡的基本單元,它的設計靈感完全來源于生物學上神經元的信息傳播機制。我們學過生物的同學都知道,神經元有兩種狀態:興奮和抑制。一般情況下,大多數的神經元是處于抑制狀態,但是一旦某個神經元收到刺激,導致它的電位超過一個閾值,那么這個神經元就會被激活,處于“興奮”狀態,進而向其他的神經元傳播化學物質(其實就是信息)。神經元是神經網絡中最基本的結構,也可以說是神經網絡的基本單元,它的設計靈感完全來源于生物學上神經元的信息傳播機制。我們學過生物的同學都知道,神經元有兩種狀態:興奮和抑制。一般情況下,大多數的神經元是處于抑制狀態,但是一旦某個神經元收到刺激,導致它的電位超過一個閾值,那么這個神經元就會被激活,處于“興奮”狀態,進而向其他的神經元傳播化學物質(其實就是信息)。
神經元的輸出需要使用激活函數,我們更常用的方法是用sigmoid函數來表示激活函數。sigmoid函數的表達式和分布圖如下所示:
(現在通常使用的是ReLU,人們起初并不覺得它的效果會好過 sigmoid 和 tanh。但是,實戰中它確實做到了。)
前向傳播
神經網絡是一種多層的前饋神經網絡,其主要的特點是:信號是前向傳播的,而誤差是反向傳播的。
假設從左面一層結點i,j,k,…等一些結點與本層的結點w有連接,那么結點w的值怎么算呢?就是通過上一層的i,j,k等結點以及對應的連接權值進行加權和運算,最終結果再加上一個偏置項,最后在通過一個非線性函數(即激活函數),如ReLu,sigmoid等函數,最后得到的結果就是本層結點w的輸出。
最終不斷的通過這種方法一層層的運算,得到輸出層結果。
矢量化
先前,我們手工對兩層、每一層只有兩節點的神經網絡進行計算。對人類而言,這樣的工作量也是足夠大了,但是如果要對五層、每層100個節點的網絡進行相同的計算,單單是寫下所有必要的計算,也是一個艱巨的任務……對每一層每一個節點,計算所有這些組合信號的組合,乘以正確的權重,應用S激活函數……
那么,矩陣如何幫助我們簡化計算呢?其實,矩陣在兩個方面幫助了我們。首先,矩陣允許我們壓縮所有這些計算,把它們變成一種非常簡單的縮寫形式。由于人類不擅長于做大量枯燥的工作,而且也很容易出錯,因此矩陣對人類幫助很大。第二個好處是,許多計算機編程語言理解如何與矩陣一起工作,計算機編程語言能夠認識到實際的工作是重復性的,因此能夠高效高速地進行計算。
總之,矩陣允許我們簡潔、方便地表示我們所需的工作,同時計算機可以快速高效地完成計算。
神經網絡中的誤差
先前,我們通過調整節點線性函數的斜率參數,來調整簡單的線性分類器。我們使用誤差值,也就是節點生成了答案與所知正確答案之間的差值,引導我們進行調整。實踐證明,誤差與所必須進行的斜率調整量之間的關系非常簡單,調整過程非常容易。
當輸出和誤差是多個節點共同作用的結果時,我們如何更新鏈接權重呢?下圖詳細闡釋了這個問題。
反向傳播
神經網絡的運作過程如下。
通過反向傳播把誤差傳播到每一層,但是怎么調整權重w
使用數學公式計算,解數學方程特別復雜
暴力枚舉,當數據量過大時不可行
這時就需要使用梯度下降
梯度下降
簡單的公式計算如下:
## 深度學習
深度學習(DeepLearning)的概念由Hinton等人于2006年提出。此外Lecun等人提出的卷積神經網絡是第一個真正多層結構學習算法,它利用空間相對關系減少參數數目以提高訓練性能。深度學習(DL)是機器學習中一種基于對數據進行表征學習的方法,是一種能夠模擬出人腦的神經結構的機器學習方法。(PS:兩位大牛因為對深度學習的巨大貢獻,因此獲得2018年圖靈獎)
說白了就是,深度學習就是深層的神經網絡,比上面介紹的三層神經網絡要復雜的多。
深度學習研究的熱潮持續高漲,各種開源深度學習框架也層出不窮,其中包括TensorFlow、Caffe、Keras、CNTK、Torch7、MXNet、Leaf、Theano、DeepLearning4、Lasagne、Neon,等等。但是上圖所示的簡單的三層神經網絡不需要使用任何深度學習框架,可以通過簡單的 Python 代碼就可以實現,下面主要講一下實現過程。
Python實現
激動人心的時刻到了,下面直接使用Python代碼,實現簡單的神經網絡。代碼的主要框架如下:
# neural network class definition class neuralNetwork : # initialise the neural network def __init__() : pass # train the neural network def train() : pass # query the neural network def query() : pass· 初始化函數—設定輸入層節點、隱藏層節點和輸出層節點的數量。
· 訓練—學習給定訓練集樣本后,優化權重。
· 查詢—給定輸入,從輸出節點給出答案。
實現的內容為識別mnist庫中的手寫數字,完整的代碼如下:
https://github.com/makeyourownneuralnetwork/makeyourownneuralnetwork
可以查看 part2_neural_network.ipynb ,如果想訓練自己手寫的圖片,可以看part3部分的代碼,另外為了增加數據集,也可以對mnist中的圖片進行旋轉等操作。
向后查詢
最后做個有意思的事情,在通常情況下,我們饋送給已受訓練的神經網絡一個問題,神經網絡彈出一個答案。在我們的例子中,這個問題是人類的手寫數字圖像。答案是表示數字0到9中的某個標簽。
如果將這種方式反轉,向后操作,會發生什么呢?如果饋送一個標簽到輸出節點,通過已受訓練的網絡反向輸入信號,直到輸入節點彈出一個圖像,那會怎么樣?下圖顯示了正常的正向查詢和瘋狂的反向向后查詢的想法。
邏輯S函數接受了任何數值,輸出0和1之間的某個值,但是不包括0和1本身。逆函數必須接受相同的范圍0和1之間的某個值,不包括0和1,彈出任何正值或負值。為了實現這一目標,我們將輸入層重新調整到有效范圍,選擇的范圍為0.01至0.99。
標簽0的結果,從圖中可以隱約的看到數字0
上圖表示了從0-9的結果,是不是有點理解神經網絡了呢?
主要參考《python神經網絡編程》,感謝作者的講解。
總結
以上是生活随笔為你收集整理的自己动手从零搭建神经网络的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 网络编程 -- 基于TCP 实
- 下一篇: 软件即服务已经过时 硬件即服务促成云计算