深度學習之卷積神經網絡入門(2)

卷積神經網絡入門學

原文地址http://blog.csdn.net/hjimce/article/details/47323463

作者:hjimce

卷積神經網絡算法是n年前就有的算法,只是近年來因爲深度學習相關算法爲多層網絡的訓練提供了新方法,然後現在電腦的計算能力已非當年的那種計算水平,同時現在的訓練數據很多,於是神經網絡的相關算法又重新火了起來因此卷積神經網絡就又活了起來。

在開始前,我們需要明確的是網上講的卷積神經網絡的相關教程一般指的是神經網絡的前向傳導過程,反向傳播都是用梯度下降法進行訓練,大部分深度學習庫,都已經把反向求導的功能給封裝好了,如果想要深入學習反向求導,就需要自己慢慢學了。

因爲卷積神經網絡的經典模型是:Lenet-5實現,只要理解了這個的前向傳導過程,基本上就OK了,因此我們後面主要講解Lenet-5的實現。

一、理論階段

作爲CNN的入門文章,沒有打算囉嗦太多的東西,因爲什麼權值共享、局部感受野什麼的,講那麼多,都是那些生物學的相關理論,看了那些玩意,大部分初學者已經煩了。卷積神經網絡的相關博文也是一大堆,但是講的,基本上都是抄過來抄過去,就像我之前不理解從S2層到C3層是怎麼實現的,網上看了一大堆教程,沒有一個解答這個問題的。我的個人感覺整個過程,就只有S2到C3是最難理解的。接着我將用最淺顯易懂的方式進行講解。

1、卷積

卷積的概念這個我想只要學過圖像處理的人都懂的概念了,這個不解釋。我們知道對於給定的一幅圖像來說,給定一個卷積核,卷積就是根據卷積窗口,進行像素的加權求和。


卷積神經網絡與我們之前所學到的圖像的卷積的區別,我的理解是:我們之前學圖像處理遇到卷積,一般來說,這個卷積核是已知的,比如各種邊緣檢測算子、高斯模糊等這些,都是已經知道卷積核,然後再與圖像進行卷積運算。然而深度學習中的卷積神經網絡卷積核是未知的,我們訓練一個神經網絡,就是要訓練得出這些卷積核,而這些卷積核就相當於我們學單層感知器的時候的那些參數W,因此你可以把這些待學習的卷積核看成是神經網絡的訓練參數W。

2、池化

剛開始學習CNN的時候,看到這個詞,好像高大上的樣子,於是查了很多資料,理論一大堆,但是實踐、算法實現卻都沒講到,也不懂池化要怎麼實現?其實所謂的池化,就是圖片下采樣。這個時候,你會發現CNN每一層的構建跟圖像高斯金字塔的構建有點類似,因此你如果已經懂得了圖像金字塔融合的相關算法,那麼就變的容易理解了。在高斯金子塔構建中,每一層通過卷積,然後卷積後進行下采樣,而CNN也是同樣的過程。廢話不多說,這裏就講一下,CNN的池化:

CNN的池化(圖像下采樣)方法很多:Mean pooling(均值採樣)、Max pooling(最大值採樣)、Overlapping (重疊採樣)、L2 pooling(均方採樣)、Local Contrast Normalization(歸一化採樣)、Stochasticpooling(隨即採樣)、Def-pooling(形變約束採樣)。其中最經典的是最大池化,因此我就解釋一下最大池化的實現:


原圖片

爲了簡單起見,我用上面的圖片作爲例子,假設上面的圖片大小是4*4的,如上圖所示,然後圖片中每個像素點的值是上面各個格子中的數值。然後我要對這張4*4的圖片進行池化,池化的大小爲(2,2),跨步爲2,那麼採用最大池化也就是對上面4*4的圖片進行分塊,每個塊的大小爲2*2,然後統計每個塊的最大值,作爲下采樣後圖片的像素值,具體計算如下圖所示:


也就是說我們最後得到下采樣後的圖片爲:


這就是所謂的最大池化。當然以後你還會遇到各種池化方法,比如均值池化,也就是對每個塊求取平均值作爲下采樣的新像素值。還有重疊採樣的池化,我上面這個例子是沒有重疊的採樣的,也就是每個塊之間沒有相互重疊的部分,上面我說的跨步爲2,就是爲了使得分塊都非重疊,等等,這些以後再跟大家解釋池化常用方法。這裏就先記住最大池化就好了,因爲這個目前是最常用的。

3、feature maps 

這個單詞國人把它翻譯成特徵圖,挺起來很專業的名詞。那麼什麼叫特徵圖呢?其實一張圖片經過一個卷積核進行卷積運算,我們可以得到一張卷積後的結果圖片,而這張圖片就是特徵圖。在CNN中,我們要訓練的卷積核並不是僅僅只有一個,這些卷積核用於提取特徵,卷積核個數越多,提取的特徵越多,理論上來說精度也會更高,然而卷積核一堆,意味着我們要訓練的參數的個數越多。在LeNet-5經典結構中,第一層卷積核選擇了6個,而在AlexNet中,第一層卷積核就選擇了96個,具體多少個合適,還有待學習。

回到特徵圖概念,CNN的每一個卷積層我們都要人爲的選取合適的卷積核個數,及卷積核大小。每個卷積核與圖片進行卷積,就可以得到一張特徵圖了,比如LeNet-5經典結構中,第一層卷積核選擇了6個,我們可以得到6個特徵圖,這些特徵圖也就是下一層網絡的輸入了。我們也可以把輸入圖片看成一張特徵圖,作爲第一層網絡的輸入。

4、CNN的經典結構

對於剛入門CNN的人來說,我們首先需要現在的一些經典結構:

(1)LeNet-5。這個是n多年前就有的一個CNN的經典結構,主要是用於手寫字體的識別,也是剛入門需要學習熟悉的一個網絡,我的這篇博文主要就是要講這個網絡


(2)AlexNet。


在imagenet上的圖像分類challenge上大神Alex提出的alexnet網絡結構模型贏得了2012屆的冠軍,振奮人心,利用CNN實現了圖片分類,別人用傳統的機器學習算法調參跳到半死也就那樣,Alex利用CNN精度遠超傳統的網絡。

其它的還有什麼《Network In Network》,GoogLeNet、Deconvolution Network,在以後的學習中我們會遇到。比如利用Deconvolution Network反捲積網絡實現圖片的去模糊,牛逼哄哄。

    OK,理論階段就囉嗦到這裏就好了,接着就講解 LeNet-5, LeNet-5是用於手寫字體的識別的一個經典CNN:


LeNet-5結構

輸入:32*32的手寫字體圖片,這些手寫字體包含0~9數字,也就是相當於10個類別的圖片

輸出:分類結果,0~9之間的一個數

因此我們可以知道,這是一個多分類問題,總共有十個類,因此神經網絡的最後輸出層必然是SoftMax問題,然後神經元的個數是10個。LeNet-5結構:

輸入層:32*32的圖片,也就是相當於1024個神經元

C1層:paper作者,選擇6個特徵卷積核,然後卷積核大小選擇5*5,這樣我們可以得到6個特徵圖,然後每個特徵圖的大小爲32-5+1=28,也就是神經元的個數由1024減小到了28*28=784。

S2層:這就是下采樣層,也就是使用最大池化進行下采樣,池化的size,選擇(2,2),也就是相當於對C1層28*28的圖片,進行分塊,每個塊的大小爲2*2,這樣我們可以得到14*14個塊,然後我們統計每個塊中,最大的值作爲下采樣的新像素,因此我們可以得到S1結果爲:14*14大小的圖片,共有6個這樣的圖片。

C3層:卷積層,這一層我們選擇卷積核的大小依舊爲5*5,據此我們可以得到新的圖片大小爲14-5+1=10,然後我們希望可以得到16張特徵圖。那麼問題來了?這一層是最難理解的,我們知道S2包含:6張14*14大小的圖片,我們希望這一層得到的結果是:16張10*10的圖片。這16張圖片的每一張,是通過S2的6張圖片進行加權組合得到的,具體是怎麼組合的呢?問題如下圖所示:


爲了解釋這個問題,我們先從簡單的開始,我現在假設輸入6特徵圖的大小是5*5的,分別用6個5*5的卷積核進行卷積,得到6個卷積結果圖片大小爲1*1,如下圖所示:


    爲了簡便起見,我這裏先做一些標號的定義:我們假設輸入第i個特徵圖的各個像素值爲x1i,x2i……x25i,因爲每個特徵圖有25個像素。因此第I個特徵圖經過5*5的圖片卷積後,得到的卷積結果圖片的像素值Pi可以表示成:


這個是卷積公式,不解釋。因此對於上面的P1~P6的計算方法,這個就是直接根據公式。然後我們把P1~P6相加起來,也就是:

P=P1+P2+……P6

把上面的Pi的計算公式,代入上式,那麼我們可以得到:

P=WX

其中X就是輸入的那6張5*5特徵圖片的各個像素點值,而W就是我們需要學習的參數,也就相當於6個5*5的卷積核,當然它包含着6*(5*5)個參數。因此我們的輸出特徵圖就是:

Out=f(P+b)

這個就是從S2到C3的計算方法,其中b表示偏置項,f爲激活函數。

我們迴歸到原來的問題:有6張輸入14*14的特徵圖片,我們希望用5*5的卷積核,然後最後我們希望得到一張10*10的輸出特徵圖片?

根據上面的過程,也就是其實我們用5*5的卷積核去卷積每一張輸入的特徵圖,當然每張特徵圖的卷積核參數是不一樣的,也就是不共享,因此我們就相當於需要6*(5*5)個參數。對每一張輸入特徵圖進行卷積後,我們得到6張10*10,新圖片,這個時候,我們把這6張圖片相加在一起,然後加一個偏置項b,然後用激活函數進行映射,就可以得到一張10*10的輸出特徵圖了。

    而我們希望得到16張10*10的輸出特徵圖,因此我們就需要卷積參數個數爲16*(6*(5*5))=16*6*(5*5)個參數。總之,C3層每個圖片是通過S2圖片進行卷積後,然後相加,並且加上偏置b,最後在進行激活函數映射得到的結果。

S4層:下采樣層,比較簡單,也是知己對C3的16張10*10的圖片進行最大池化,池化塊的大小爲2*2。因此最後S4層爲16張大小爲5*5的圖片。至此我們的神經元個數已經減少爲:16*5*5=400。

C5層:我們繼續用5*5的卷積核進行卷積,然後我們希望得到120個特徵圖。這樣C5層圖片的大小爲5-5+1=1,也就是相當於1個神經元,120個特徵圖,因此最後只剩下120個神經元了。這個時候,神經元的個數已經夠少的了,後面我們就可以直接利用全連接神經網絡,進行這120個神經元的後續處理,後面具體要怎麼搞,只要懂多層感知器的都懂了,不解釋。

上面的結構,只是一種參考,在現實使用中,每一層特徵圖需要多少個,卷積核大小選擇,還有池化的時候採樣率要多少,等這些都是變化的,這就是所謂的CNN調參,我們需要學會靈活多變。

比如我們可以把上面的結構改爲:C1層卷積核大小爲7*7,然後把C3層卷積核大小改爲3*3等,然後特徵圖的個數也是自己選,說不定得到手寫字體識別的精度比上面那個還高,這也是有可能的,總之一句話:需要學會靈活多變,需要學會CNN的調參。

二、實戰階段

學習CNN的源碼實現網站:http://deeplearning.net/tutorial/lenet.html#lenet

1、訓練數據獲取

在theano學習庫中有手寫字體的庫,可以從網上下載到,名爲:mnist.pkl.gz的手寫字體庫,裏面包含了三個部分的數據,訓練數據集train_set:50000個訓練樣本,驗證集valid_set,我們可以用如下的代碼讀取這些數據,然後用plot顯示其中的一張圖片:

  1. <span style="font-size:18px;">import cPickle  
  2. import gzip  
  3. import numpy as np  
  4. import matplotlib.pyplot as plt  
  5. f = gzip.open('mnist.pkl.gz''rb')  
  6. train_set, valid_set, test_set = cPickle.load(f)  
  7. f.close()  
  8. tx,ty=train_set;  
  9.   
  10. #查看訓練樣本  
  11. print np.shape(tx)#可以看到tx大小爲(50000,28*28)的二維矩陣  
  12. print np.shape(ty)#可以看到ty大小爲(50000,1)的矩陣  
  13. #圖片顯示  
  14. A=tx[8].reshape(28,28)#第八個訓練樣本  
  15. Y=ty[8]  
  16. print Y  
  17. plt.imshow(A,cmap='gray')#顯示手寫字體圖片</span>  

在上面的代碼中我顯示的是第8張圖片,可以看到如下結果:


第八個樣本是數字1。

2、LeNet-5實現

首先你要知道mnist.pkl.gz這個庫給我們的圖片的大小是28*28的,因此我們可以第一步選擇5*5的卷積核進行卷積得到24*24,同時我們希望C1層得到20張特徵圖,等等,具體的代碼實現如下;

  1. import os  
  2. import sys  
  3. import timeit  
  4.   
  5. import numpy  
  6.   
  7. import theano  
  8. import theano.tensor as T  
  9. from theano.tensor.signal import downsample  
  10. from theano.tensor.nnet import conv  
  11.   
  12. from logistic_sgd import LogisticRegression, load_data  
  13. from mlp import HiddenLayer  
  14.   
  15. #卷積神經網絡的一層,包含:卷積+下采樣兩個步驟  
  16. #算法的過程是:卷積-》下采樣-》激活函數  
  17. class LeNetConvPoolLayer(object):  
  18.   
  19.     #image_shape是輸入數據的相關參數設置  filter_shape本層的相關參數設置  
  20.     def __init__(self, rng, input, filter_shape, image_shape, poolsize=(22)):  
  21.         """ 
  22.         :type rng: numpy.random.RandomState 
  23.         :param rng: a random number generator used to initialize weights 
  24.  
  25.         3、input: 輸入特徵圖數據,也就是n幅特徵圖片 
  26.  
  27.         4、參數 filter_shape: (number of filters, num input feature maps, 
  28.                               filter height, filter width) 
  29.         num of filters:是卷積核的個數,有多少個卷積核,那麼本層的out feature maps的個數 
  30.         也將生成多少個。num input feature maps:輸入特徵圖的個數。 
  31.         然後接着filter height, filter width是卷積核的寬高,比如5*5,9*9…… 
  32.         filter_shape是列表,因此我們可以用filter_shape[0]獲取卷積核個數 
  33.  
  34.         5、參數 image_shape: (batch size, num input feature maps, 
  35.                              image height, image width), 
  36.          batch size:批量訓練樣本個數 ,num input feature maps:輸入特徵圖的個數 
  37.          image height, image width分別是輸入的feature map圖片的大小。 
  38.          image_shape是一個列表類型,所以可以直接用索引,訪問上面的4個參數,索引下標從 
  39.          0~3。比如image_shape[2]=image_heigth  image_shape[3]=num input feature maps 
  40.  
  41.         6、參數 poolsize: 池化下采樣的的塊大小,一般爲(2,2) 
  42.         """  
  43.   
  44.         assert image_shape[1] == filter_shape[1]#判斷輸入特徵圖的個數是否一致,如果不一致是錯誤的  
  45.         self.input = input  
  46.   
  47.         # fan_in=num input feature maps *filter height*filter width   
  48.         #numpy.prod(x)函數爲計算x各個元素的乘積  
  49.         #也就是說fan_in就相當於每個即將輸出的feature  map所需要鏈接參數權值的個數  
  50.         fan_in = numpy.prod(filter_shape[1:])  
  51.         # fan_out=num output feature maps * filter height * filter width  
  52.         fan_out = (filter_shape[0] * numpy.prod(filter_shape[2:]) /  
  53.                    numpy.prod(poolsize))  
  54.         # 把參數初始化到[-a,a]之間的數,其中a=sqrt(6./(fan_in + fan_out)),然後參數採用均勻採樣  
  55.         #權值需要多少個?卷積核個數*輸入特徵圖個數*卷積核寬*卷積核高?這樣沒有包含採樣層的鏈接權值個數  
  56.         W_bound = numpy.sqrt(6. / (fan_in + fan_out))  
  57.         self.W = theano.shared(  
  58.             numpy.asarray(  
  59.                 rng.uniform(low=-W_bound, high=W_bound, size=filter_shape),  
  60.                 dtype=theano.config.floatX  
  61.             ),  
  62.             borrow=True  
  63.         )  
  64.   
  65.         # b爲偏置,是一維的向量。每個輸出特徵圖i對應一個偏置參數b[i]  
  66.         #,因此下面初始化b的個數就是特徵圖的個數filter_shape[0]  
  67.         b_values = numpy.zeros((filter_shape[0],), dtype=theano.config.floatX)  
  68.         self.b = theano.shared(value=b_values, borrow=True)  
  69.   
  70.         # 卷積層操作,函數conv.conv2d的第一個參數爲輸入的特徵圖,第二個參數爲隨機出事化的卷積核參數  
  71.         #第三個參數爲卷積核的相關屬性,輸入特徵圖的相關屬性  
  72.         conv_out = conv.conv2d(  
  73.             input=input,  
  74.             filters=self.W,  
  75.             filter_shape=filter_shape,  
  76.             image_shape=image_shape  
  77.         )  
  78.   
  79.         # 池化操作,最大池化  
  80.         pooled_out = downsample.max_pool_2d(  
  81.             input=conv_out,  
  82.             ds=poolsize,  
  83.             ignore_border=True  
  84.         )  
  85.         #激勵函數,也就是說是先經過卷積核再池化後,然後在進行非線性映射  
  86.         # add the bias term. Since the bias is a vector (1D array), we first  
  87.         # reshape it to a tensor of shape (1, n_filters, 1, 1). Each bias will  
  88.         # thus be broadcasted across mini-batches and feature map  
  89.         # width & height  
  90.         self.output = T.tanh(pooled_out + self.b.dimshuffle('x'0'x''x'))  
  91.   
  92.         # 保存參數  
  93.         self.params = [self.W, self.b]  
  94.         self.input = input  
  95.   
  96. #測試函數  
  97. def evaluate_lenet5(learning_rate=0.1, n_epochs=200,  
  98.                     dataset='mnist.pkl.gz',  
  99.                     nkerns=[2050], batch_size=500):  
  100.     """ Demonstrates lenet on MNIST dataset 
  101.  
  102.  
  103.     :learning_rate: 梯度下降法的學習率 
  104.  
  105.     :n_epochs: 最大迭代次數 
  106.  
  107.     :type dataset: string 
  108.     :param dataset: path to the dataset used for training /testing (MNIST here) 
  109.  
  110.     :nkerns: 每個卷積層的卷積核個數,第一層卷積核個數爲 nkerns[0]=20,第二層卷積核個數 
  111.     爲50個 
  112.     """  
  113.   
  114.     rng = numpy.random.RandomState(23455)  
  115.   
  116.     datasets = load_data(dataset)#加載訓練數據,訓練數據包含三個部分  
  117.   
  118.     train_set_x, train_set_y = datasets[0]#訓練數據  
  119.     valid_set_x, valid_set_y = datasets[1]#驗證數據  
  120.     test_set_x, test_set_y = datasets[2]#測試數據  
  121.   
  122.     # 計算批量訓練可以分多少批數據進行訓練,這個只要是知道批量訓練的人都知道  
  123.     n_train_batches = train_set_x.get_value(borrow=True).shape[0]#訓練數據個數  
  124.     n_valid_batches = valid_set_x.get_value(borrow=True).shape[0]  
  125.     n_test_batches = test_set_x.get_value(borrow=True).shape[0]  
  126.     n_train_batches /= batch_size#批數  
  127.     n_valid_batches /= batch_size  
  128.     n_test_batches /= batch_size  
  129.   
  130.     # allocate symbolic variables for the data  
  131.     index = T.lscalar()  # index to a [mini]batch  
  132.   
  133.     # start-snippet-1  
  134.     x = T.matrix('x')   # the data is presented as rasterized images  
  135.     y = T.ivector('y')  # the labels are presented as 1D vector of  
  136.                         # [int] labels  
  137.   
  138.   
  139.     # Reshape matrix of rasterized images of shape (batch_size, 28 * 28)  
  140.     # to a 4D tensor, compatible with our LeNetConvPoolLayer  
  141.     # (28, 28) is the size of MNIST images.  
  142.     layer0_input = x.reshape((batch_size, 12828))  
  143.   
  144.     '''''構建第一層網絡: 
  145.     image_shape:輸入大小爲28*28的特徵圖,batch_size個訓練數據,每個訓練數據有1個特徵圖 
  146.     filter_shape:卷積核個數爲nkernes[0]=20,因此本層每個訓練樣本即將生成20個特徵圖 
  147.     經過卷積操作,圖片大小變爲(28-5+1 , 28-5+1) = (24, 24) 
  148.     經過池化操作,圖片大小變爲 (24/2, 24/2) = (12, 12) 
  149.     最後生成的本層image_shape爲(batch_size, nkerns[0], 12, 12)'''  
  150.     layer0 = LeNetConvPoolLayer(  
  151.         rng,  
  152.         input=layer0_input,  
  153.         image_shape=(batch_size, 12828),  
  154.         filter_shape=(nkerns[0], 155),  
  155.         poolsize=(22)  
  156.     )  
  157.   
  158.     '''''構建第二層網絡:輸入batch_size個訓練圖片,經過第一層的卷積後,每個訓練圖片有nkernes[0]個特徵圖,每個特徵圖 
  159.     大小爲12*12 
  160.     經過卷積後,圖片大小變爲(12-5+1, 12-5+1) = (8, 8) 
  161.     經過池化後,圖片大小變爲(8/2, 8/2) = (4, 4) 
  162.     最後生成的本層的image_shape爲(batch_size, nkerns[1], 4, 4)'''  
  163.     layer1 = LeNetConvPoolLayer(  
  164.         rng,  
  165.         input=layer0.output,  
  166.         image_shape=(batch_size, nkerns[0], 1212),  
  167.         filter_shape=(nkerns[1], nkerns[0], 55),  
  168.         poolsize=(22)  
  169.     )  
  170.   
  171.     # the HiddenLayer being fully-connected, it operates on 2D matrices of  
  172.     # shape (batch_size, num_pixels) (i.e matrix of rasterized images).  
  173.     # This will generate a matrix of shape (batch_size, nkerns[1] * 4 * 4),  
  174.     # or (500, 50 * 4 * 4) = (500, 800) with the default values.  
  175.     layer2_input = layer1.output.flatten(2)  
  176.   
  177.     '''''全鏈接:輸入layer2_input是一個二維的矩陣,第一維表示樣本,第二維表示上面經過卷積下采樣後 
  178.     每個樣本所得到的神經元,也就是每個樣本的特徵,HiddenLayer類是一個單層網絡結構 
  179.     下面的layer2把神經元個數由800個壓縮映射爲500個'''  
  180.     layer2 = HiddenLayer(  
  181.         rng,  
  182.         input=layer2_input,  
  183.         n_in=nkerns[1] * 4 * 4,  
  184.         n_out=500,  
  185.         activation=T.tanh  
  186.     )  
  187.   
  188.     # 最後一層:邏輯迴歸層分類判別,把500個神經元,壓縮映射成10個神經元,分別對應於手寫字體的0~9  
  189.     layer3 = LogisticRegression(input=layer2.output, n_in=500, n_out=10)  
  190.   
  191.     # the cost we minimize during training is the NLL of the model  
  192.     cost = layer3.negative_log_likelihood(y)  
  193.   
  194.     # create a function to compute the mistakes that are made by the model  
  195.     test_model = theano.function(  
  196.         [index],  
  197.         layer3.errors(y),  
  198.         givens={  
  199.             x: test_set_x[index * batch_size: (index + 1) * batch_size],  
  200.             y: test_set_y[index * batch_size: (index + 1) * batch_size]  
  201.         }  
  202.     )  
  203.   
  204.     validate_model = theano.function(  
  205.         [index],  
  206.         layer3.errors(y),  
  207.         givens={  
  208.             x: valid_set_x[index * batch_size: (index + 1) * batch_size],  
  209.             y: valid_set_y[index * batch_size: (index + 1) * batch_size]  
  210.         }  
  211.     )  
  212.   
  213.     #把所有的參數放在同一個列表裏,可直接使用列表相加  
  214.     params = layer3.params + layer2.params + layer1.params + layer0.params  
  215.   
  216.     #梯度求導  
  217.     grads = T.grad(cost, params)  
  218.   
  219.     # train_model is a function that updates the model parameters by  
  220.     # SGD Since this model has many parameters, it would be tedious to  
  221.     # manually create an update rule for each model parameter. We thus  
  222.     # create the updates list by automatically looping over all  
  223.     # (params[i], grads[i]) pairs.  
  224.     updates = [  
  225.         (param_i, param_i - learning_rate * grad_i)  
  226.         for param_i, grad_i in zip(params, grads)  
  227.     ]  
  228.   
  229.     train_model = theano.function(  
  230.         [index],  
  231.         cost,  
  232.         updates=updates,  
  233.         givens={  
  234.             x: train_set_x[index * batch_size: (index + 1) * batch_size],  
  235.             y: train_set_y[index * batch_size: (index + 1) * batch_size]  
  236.         }  
  237.     )  
  238.     # end-snippet-1  
  239.   
  240.     ###############  
  241.     # TRAIN MODEL #  
  242.     ###############  
  243.     print '... training'  
  244.     # early-stopping parameters  
  245.     patience = 10000  # look as this many examples regardless  
  246.     patience_increase = 2  # wait this much longer when a new best is  
  247.                            # found  
  248.     improvement_threshold = 0.995  # a relative improvement of this much is  
  249.                                    # considered significant  
  250.     validation_frequency = min(n_train_batches, patience / 2)  
  251.                                   # go through this many  
  252.                                   # minibatche before checking the network  
  253.                                   # on the validation set; in this case we  
  254.                                   # check every epoch  
  255.   
  256.     best_validation_loss = numpy.inf  
  257.     best_iter = 0  
  258.     test_score = 0.  
  259.     start_time = timeit.default_timer()  
  260.   
  261.     epoch = 0  
  262.     done_looping = False  
  263.   
  264.     while (epoch < n_epochs) and (not done_looping):  
  265.         epoch = epoch + 1  
  266.         for minibatch_index in xrange(n_train_batches):#每一批訓練數據  
  267.   
  268.             cost_ij = train_model(minibatch_index)  
  269.             iter = (epoch - 1) * n_train_batches + minibatch_index  
  270.             if (iter + 1) % validation_frequency == 0:  
  271.   
  272.                 # compute zero-one loss on validation set  
  273.                 validation_losses = [validate_model(i) for i  
  274.                                      in xrange(n_valid_batches)]  
  275.                 this_validation_loss = numpy.mean(validation_losses)  
  276.                 print('epoch %i, minibatch %i/%i, validation error %f %%' %  
  277.                       (epoch, minibatch_index + 1, n_train_batches,  
  278.                        this_validation_loss * 100.))  
  279.   
  280.                 # if we got the best validation score until now  
  281.                 if this_validation_loss < best_validation_loss:  
  282.   
  283.                     #improve patience if loss improvement is good enough  
  284.                     if this_validation_loss < best_validation_loss *  \  
  285.                        improvement_threshold:  
  286.                         patience = max(patience, iter * patience_increase)  
  287.   
  288.                     # save best validation score and iteration number  
  289.                     best_validation_loss = this_validation_loss  
  290.                     best_iter = iter  
  291.   
  292.                     # test it on the test set  
  293.                     test_losses = [  
  294.                         test_model(i)  
  295.                         for i in xrange(n_test_batches)  
  296.                     ]  
  297.                     test_score = numpy.mean(test_losses)  
  298.                     print(('     epoch %i, minibatch %i/%i, test error of '  
  299.                            'best model %f %%') %  
  300.                           (epoch, minibatch_index + 1, n_train_batches,  
  301.                            test_score * 100.))  
  302.   
  303.             if patience <= iter:  
  304.                 done_looping = True  
  305.                 break  
  306.   
  307.     end_time = timeit.default_timer()  
  308.     print('Optimization complete.')  
  309.     print('Best validation score of %f %% obtained at iteration %i, '  
  310.           'with test performance %f %%' %  
  311.           (best_validation_loss * 100., best_iter + 1, test_score * 100.))  
  312.     print >> sys.stderr, ('The code for file ' +  
  313.                           os.path.split(__file__)[1] +  
  314.                           ' ran for %.2fm' % ((end_time - start_time) / 60.))  
  315.   
  316. if __name__ == '__main__':  
  317.     evaluate_lenet5()  
  318.   
  319.   
  320. def experiment(state, channel):  
  321.     evaluate_lenet5(state.learning_rate, dataset=state.dataset)  

訓練結果:


參考文獻:

1、http://blog.csdn.net/zouxy09/article/details/8775360/

2、http://www.deeplearning.net/tutorial/lenet.html#lenet

**********************作者:hjimce   時間:2015.8.6  聯繫QQ:1393852684   地址:http://blog.csdn.net/hjimce 轉載請保留本行信息********************
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章