如何用NumPy搭建卷積神經網絡實現手寫數字識別(附代碼)

0 1

介紹

當Yann LeCun發表了他關於開發一種新型神經網絡架構——卷積神經網絡(Convolutional neural network, CNN)——的研究成果時,他的工做基本上沒有引發注意。在2012年的ImageNet計算機視覺大賽上,來自多倫多大學的一組研究人員花了14年的時間將CNN引入公衆視野。當他們從數千個類別的中對數百萬張圖片進行分類時,只產生了15.8%的錯誤。快進到如今,當前最早進的卷積神經網絡實現的精度超過人類水平的性能。git


ImageNet數據集上錯誤率
github


在這些有但願的結果的激勵下,我開始瞭解CNN的功能,以及它們是如何表現得如此出色的。所以爲了全面瞭解人工智能的這種進步,我在NumPy中從零開始構建了一個卷積神經網絡。在完成這個項目以後,我以爲卷積神經網絡在表面複雜性和它們實際複雜性之間存在着脫節。算法

0 2

挑戰

CNN以其識別圖像模式的能力而聞名,所以本文中描述的網絡的任務就是圖像分類。衡量計算機視覺算法執行狀況的最多見基準之一是在MNIST手寫數字數據庫上對其進行訓練:該數據庫包含70,000個手寫數字及其對應的標籤。目標是訓練CNN在標記手寫數字(從0到9)時儘量準確。通過大約5個小時的訓練和在訓練集上的兩次循環,這裏展現的網絡可以在測試數據上達到98%的準確率,這意味着它能夠正確地猜想顯示給它的幾乎每個手寫數字。數據庫




讓咱們回顧一下構成網絡的各個組件,以及它們如何鏈接在一塊兒,從輸入數據造成預測。在解釋了每一個組件以後,咱們將對其功能進行編碼。在這篇文章的最後一部分,咱們將使用NumPy對網絡的每一個部分進行編程和訓練。廢話少說,讓咱們開始吧。編程

0 3

卷積神經網絡如何學習



卷積層(Convolutions)微信


CNN利用過濾器(也被稱爲內核)來檢測圖像中存在哪些特徵,好比邊緣。過濾器只是一個值的矩陣,叫作權值,它被訓練來檢測特定的特徵。過濾器移動到圖像的每一個部分,檢查它要檢測的特徵是否存在。爲了提供一個值來表示特定特徵的可信度,過濾器執行一個卷積操做,這是一個元素的乘積和兩個矩陣之間的和。網絡




當特徵出如今圖像的某一部分時,濾波器與該部分圖像進行卷積運算,獲得一個高值的實數。若是特性不存在,則結果值很低。架構


在下面的例子中,負責檢查右邊曲線的過濾器被傳遞到圖像的一部分。因爲圖像的這一部分包含與濾波器所尋找的曲線相同的曲線,所以卷積運算的結果是一個很大的數(6600)。機器學習



可是,當相同的濾波器經過圖像中具備至關不一樣的邊緣集的部分時,卷積的輸出很小,這意味着不存在很強的右手曲線。編輯器




爲了使卷積神經網絡可以學習檢測輸入數據中特徵的濾波器的值,必須經過非線性映射來傳遞濾波器。濾波器與輸入圖像卷積運算的輸出用偏置項求和,並經過非線性激活函數。激活函數的目的是將非線性引入到咱們的網絡中。因爲咱們的輸入數據是非線性的(對造成手寫簽名的像素進行線性建模是不可行的),咱們的模型須要考慮這一點


代碼要點:


使用NumPy,咱們能夠很容易地對卷積運算進行編程。卷積函數利用for循環對圖像上的全部過濾器進行卷積。在for循環的每一個迭代中,使用兩個while循環將過濾器傳遞給圖像。在每一個步驟中,過濾器是多元素的(*)與輸入圖像的一部分。而後使用NumPy 's sum方法將這個元素相乘的結果求和,獲得一個單獨的值,而後添加一個誤差項。


縮減像素採樣(Downsampling)


爲了加快訓練過程並減小網絡消耗的內存,咱們嘗試減小輸入特性中存在的冗餘。有幾種方法能夠對圖像進行降採樣,但在這篇文章中,咱們將着眼於最多見的一種:max pooling(最大池化)。


最大池化中,一個窗口根據設定的步長(每次移動多少單位)從一個圖像上通過。在每一個步驟中,窗口內的最大值被合併到一個輸出矩陣中,所以稱爲最大池化


在下面的圖像中,大小爲f=2的窗口以2的步長經過圖像。f表示最大池化窗口的大小(紅色框),s表示窗口在x和y方向上移動的單元數。在每一個步驟中,選擇窗口內的最大值:




最大池化極大地減小了表示大小,從而減小了所需的內存數量和之後在網絡中執行的操做數量。


代碼要點:

最大池操做歸結爲一個for循環和幾個while循環。for循環用於遍歷輸入圖像的每一層,while循環將窗口滑動到圖像的每一個部分。在每一個步驟中,咱們使用NumPy的max方法來得到最大值


全鏈接層(fully-connected layer)


在神經網絡的全連通操做中,輸入表示被壓扁成一個特徵向量,並經過神經元網絡來預測輸出機率。


這些行被鏈接起來造成一個長特徵向量。若是存在多個輸入層,則將其行鏈接起來造成更長的特徵向量。


而後將特徵向量經過多個密集層。在每一稠密層,特徵向量乘以該層的權值,加上它的誤差,而後經過非線性。下圖顯示了全連通操做和稠密層:



代碼要點:

NumPy使得編寫CNN的全鏈接層變得很是簡單。事實上,你能夠用NumPy的reshape方法在一行代碼中完成


輸出層(Output layer)


CNN的輸出層負責生成給定輸入圖像的每一個類(每一個數字)的機率。爲了得到這些機率,咱們初始化最後的緻密層,使其包含與類相同數量的神經元。而後,這個稠密層的輸出經過Softmax激活函數,該函數將全部最終的稠密層輸出映射到一個元素之和爲1的向量。

04

結果

通過訓練,網絡在測試集上的準確率平均爲98%,我認爲這是至關不錯的。將訓練時間延長2-3個epoch後,我發現測試集的性能降低了。我推測,在第三到第四個訓練循環中,網絡開始過分擬合訓練集,再也不泛化。



做者:Alejandro Escontrela

編譯:HuangweiAI

原文連接:閱讀原文

代碼連接(NumPy版):https://github.com/Alescontrela/Numpy-CNN

·END·
 

掃碼關注

機器學習·數據分析


本文分享自微信公衆號 - Python學會(gh_39aead19f756)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索