Connections 僅僅作為Connection的集合對象,提供一些集合操作。
Node實(shí)現(xiàn)如下:


ConstNode對象,為了實(shí)現(xiàn)一個輸出恒為1的節(jié)點(diǎn)(計(jì)算偏置項(xiàng)時(shí)需要)

Layer對象,負(fù)責(zé)初始化一層。此外,作為Node的集合對象,提供對Node集合的操作。

Connection對象,主要職責(zé)是記錄連接的權(quán)重,以及這個連接所關(guān)聯(lián)的上下游節(jié)點(diǎn)。


Connections對象,提供Connection集合操作。

Network對象,提供API。



至此,實(shí)現(xiàn)了一個基本的全連接神經(jīng)網(wǎng)絡(luò)。可以看到,同神經(jīng)網(wǎng)絡(luò)的強(qiáng)大學(xué)習(xí)能力相比,其實(shí)現(xiàn)還算是很容易的。
梯度檢查
怎么保證自己寫的神經(jīng)網(wǎng)絡(luò)沒有BUG呢?事實(shí)上這是一個非常重要的問題。一方面,千辛萬苦想到一個算法,結(jié)果效果不理想,那么是算法本身錯了還是代碼實(shí)現(xiàn)錯了呢?定位這種問題肯定要花費(fèi)大量的時(shí)間和精力。另一方面,由于神經(jīng)網(wǎng)絡(luò)的復(fù)雜性,我們幾乎無法事先知道神經(jīng)網(wǎng)絡(luò)的輸入和輸出,因此類似TDD(測試驅(qū)動開發(fā))這樣的開發(fā)方法似乎也不可行。
辦法還是有滴,就是利用梯度檢查來確認(rèn)程序是否正確。梯度檢查的思路如下:

對于梯度下降算法:

當(dāng)然,我們可以重復(fù)上面的過程,對每個權(quán)重Wji 都進(jìn)行檢查。也可以使用多個樣本重復(fù)檢查。

至此,會推導(dǎo)、會實(shí)現(xiàn)、會抓BUG,你已經(jīng)摸到深度學(xué)習(xí)的大門了。接下來還需要不斷的實(shí)踐,我們用剛剛寫過的神經(jīng)網(wǎng)絡(luò)去識別手寫數(shù)字。
神經(jīng)網(wǎng)絡(luò)實(shí)戰(zhàn)——手寫數(shù)字識別
針對這個任務(wù),我們采用業(yè)界非常流行的MNIST數(shù)據(jù)集。MNIST大約有60000個手寫字母的訓(xùn)練樣本,我們使用它訓(xùn)練我們的神經(jīng)網(wǎng)絡(luò),然后再用訓(xùn)練好的網(wǎng)絡(luò)去識別手寫數(shù)字。
手寫數(shù)字識別是個比較簡單的任務(wù),數(shù)字只可能是0-9中的一個,這是個10分類問題。
超參數(shù)的確定
我們首先需要確定網(wǎng)絡(luò)的層數(shù)和每層的節(jié)點(diǎn)數(shù)。關(guān)于第一個問題,實(shí)際上并沒有什么理論化的方法,大家都是根據(jù)經(jīng)驗(yàn)來拍,如果沒有經(jīng)驗(yàn)的話就隨便拍一個。然后,你可以多試幾個值,訓(xùn)練不同層數(shù)的神經(jīng)網(wǎng)絡(luò),看看哪個效果最好就用哪個。嗯,現(xiàn)在你可能明白為什么說深度學(xué)習(xí)是個手藝活了,有些手藝很讓人無語,而有些手藝還是很有技術(shù)含量的。
不過,有些基本道理我們還是明白的,我們知道網(wǎng)絡(luò)層數(shù)越多越好,也知道層數(shù)越多訓(xùn)練難度越大。對于全連接網(wǎng)絡(luò),隱藏層最好不要超過三層。那么,我們可以先試試僅有一個隱藏層的神經(jīng)網(wǎng)絡(luò)效果怎么樣。畢竟模型小的話,訓(xùn)練起來也快些(剛開始玩模型的時(shí)候,都希望快點(diǎn)看到結(jié)果)。