2017年5月20日 星期六

深度學習(4)--使用Tensorflow實現類Lenet5手寫數字辨識


    這一節介紹一完整的手寫數字辨識的範例,使用Tensorflow來實現類似Lenet5的架構。除了使用MNIST數據集來做訓練與測試外,我們將訓練好的模型儲存起來,並用微軟小畫家自行手寫幾張數字來進行實際的辨識預測,最後使用Kaggle網站上的手寫數字數據進行預測,並將結果上傳至kaggle網站上打分數,得到預測的成績。

   本文主要提供程式實作,不會再提到太多相關的理論,有關相關的理論,大多可以在最底下之前提過的文章或參考資料閱讀相關理論。這個程式的建立環境是python 3.5 +tensorflow1.10 win10底下使用GPU加速運算,估計跑在Linux或是純CPU運算應該也沒太大問題。


首先來回顧Lenet5的經典架構,如下<圖一>
Lenet5模型是Yann LeCun教授於1998年在論文Gradient-based learning applied to document recognition中提出的,它是第一個成功應用於數字識別問題的卷積神經網路。在MNIST數據集上,Lenet5模型可以達到大約99.2%的正確率,Lenet5模型總共有7層。

有關CNN卷積神經網路的介紹可參閱之前文章:
深度學習(2)--使用Tensorflow實作卷積神經網路(Convolutional neural network,CNN)

<圖一>Lenet5架構


第一層 卷積層(Convolution)
    這一層的輸入就是原始圖像像素,Lenet5接受的輸入層大小為32x32x1。第一個卷積層filter的尺寸為5x5,深度為6,不使用zero padding,步長(Stride)為1,故這一層輸出的尺寸為32-5+1=28,深度為6。總共有5x5x1x6+6=156個參數,其中6為bias偏誤。因下一層節點矩陣有28x28x6=4704個節點,每個節點和5x5=25個節點相連,所以本層卷積層總共有4707x(25+1)=122304個連接。

第二層 池化層(Pooling)
    這一層的輸入為第一層的輸出,是一28x28x6的節點矩陣,本層採用的filter為2x2,stride=2,故輸出矩陣大小為14x14x6。

第三層 卷積層(Convolution)
    本層的輸入矩陣大小為14x14x6,使用的filter為5x5,深度為16,不使用Zero padding,stride=1,本層的輸出矩陣大小為10x10x6。因此本層應該有5x5x6x16+16=2416個參數,
10x10x16x(25+1)=41600個連接。

第四層 池化層(Pooling)
    本層的輸入矩陣大小為10x10x16,採用filter為2x2,stride為2,本層的輸出矩陣大小為5x5x16。

第五層 卷積層(Convolution)
    本層的輸入矩陣大小為5x5x16,在Lenet5模型的論文終將這一層稱為卷積層,但是因為filter大小即為5x5,所以和全連接層沒有區別,如果將5x5x16節點拉成一個向量,那麼這一層就和全連接層一樣,本層的輸出節點數為120,總共有5x5x16x120+120=48120個參數。

第六層 全連接層
    本層的輸入節點數為120個,輸出節點數為84個,參數總共為120x84+84=10164個。

第七層 全連接層
    本層的輸入節點數為84個,輸出節點為10個,參數總共為84x10+10=850個。

底下會使用Tensorflow來實現類似Lenet5的架構如下<圖二>
在卷積層因為使用了Zero padding所以,圖像尺寸不會縮小
在程式裡是以padding='SAME'來宣告。
conv1 = tf.nn.conv2d(input_tensor, conv1_weights, strides=[1, 1, 1, 1], padding='SAME')

<圖二>

2017年5月7日 星期日

深度學習(3)--循環神經網絡(RNN, Recurrent Neural Networks)


    本節介紹最簡單的循環神經網路,稱之為Simple-RNN,它是LSTM的基礎。Simple-RNN與BP一樣都有前饋層與反饋層。但是Simple-RNN引入了基於時間(狀態)的循環機制。

    下圖一所示為Simple-RNN的神經網路示意圖。神經網路為A,通過讀取某個時間(狀態)的
輸入xt,然後輸出一個值ht,循環可以使得信息從當前時間步傳遞到下一時間步。
    這些循環使得RNN可以被看作同一網路在不同時間步的多次循環,每個神經元會把更新的結果傳遞給下一個時間步,下圖一右側即為循環展開的情形。


<圖一>