使用Numpy訓練基於MNIST數據集的深度卷積神經網絡

在《Fundamentals of Deep Learning》一書中,作者將深度神經網絡中的隱藏層的作用描述爲"This is where most of the magic is happening when the neural net tries to solve problems";不過,從計算的角度來看,深度神經網絡是一種功能強大的非線性變換,各個層的權重有着特定的處理數據的方式。然而,僅僅瞭解到深度神經網絡的前向計算過程,是不夠的;最好也能夠對“雕刻”這些權重的反向傳播有一定的瞭解。本文記錄了筆者基於NumPy實現的簡單深度卷積神經網絡的訓練方法,訓練了LeNet5網絡和《Python Machine Learning, 2nd》中的一個由TensorFlow改編的網絡。經測試,訓練的網絡模型對MNIST數據集進行分類的準確度分別達到98%和96%以上。本文的代碼可以在https://github.com/LinkYe/LearnDeep/tree/master/mnist-train中獲得。

利用深度神經網絡各層之間的相似性,筆者建立了卷積層ConvLayer、全連接層FullConLayer、池化層MaxPoolLayer和SoftMaxLayer,分別在單獨的Python代碼中實現。這些層有相似的Python類方法接口,即forward(...)和backward(...),這樣就可以將這些層存放在列表中遍歷調用,簡化了前向和反向的調用過程。爲了簡化損失的計算,筆者將MSE作爲損失函數的度量。詳細的實現可參考MnistModel.py的內容。

將train-images-idx3-ubyte.gz及train-labels-idx1-ubyte.gz解壓後複製到mnist-train目錄下,就可以進行訓練了。
訓練lenet5網絡的方法是在命令行執行:python3 -i MnistModel.py lenet5,一般配置中等的電腦一兩個小時可以完成訓練,其結果如下圖:

訓練另一個不知名的網絡,則在命令行執行 python3 -i MnistModel.py,該網絡的訓練效率與lenet5相較而言,是很低的。以筆者的電腦來看,需訓練一天的時間,下圖是訓練的過程:

由比較可知,Lenet5網絡的效率、準確率要高很多,很大程度上優越於後者。這一方面是LeNet5網絡權重參數更少(這樣訓練得越快),另一方面也是因爲LeNet5網絡更深了一層。還有,LeNet5的學習率(Learning Rate)爲0.01,而後者的LR爲0.0001。筆者曽把後者的LR設置爲0.01,結果出現了浮點數溢出的問題,可見訓練一個神經網絡,模型參數的選擇是很重要的。

最後一點重要的就是反向傳播(Backpropagation)算法的實現了。在《深度學習基礎》第二章有過這方面的論述,雖然只是大致的思路,且只是針對全連接層而言的,但核心的思想體現出來了,即從輸出層開始對各層的輸出結果計算差值(或者說,離散的微分),依次計算各層權重的微分,然後更新權重。對於卷積層的反向傳播計算,論文《Notes on Convolutional Neural Networks》有詳細的推導過程。這裏需要注意的是,對於卷積層的計算,需要將卷積核上下、左右翻轉,這一點在博客 https://grzegorzgwardys.wordpress.com/2016/04/22/8/ 中有詳細的討論。
對於輸出層的softMax的求導,這裏參考了 https://eli.thegreenplace.net/2016/the-softmax-function-and-its-derivative/ 的推導過程。有興趣的可以參考代碼一下這些鏈接和論文,加深對反向傳播的理解。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章