初試cnn(1)

         前幾天,老闆安排任務了,要求找個卷積網絡的c++代碼自己跑一下試試,雖然有點矇蔽可是還要去做,搜了很多代碼,基本上都是從hithub.com裏下載的代碼,裏面基本都是開源的代碼,而且是經過測試沒有問題的,補充一句,在這個網站串代碼的人每個人都很厲害,程序近乎是完美的,大家在搞懂其中原理之後建議去學習一下人家的寫作思路是怎樣的。首先,建議大家跑一下tiny_cnn,這個比較簡單。可以直接打開VC裏面的vc12的vc++ pro,裏面都是包裝好的,先運行一下試試,炮成功之後再看代碼。

(1)程序來源:         代碼包下載地址:https://github.com/tiny-dnn/tiny-dnn,下載完之後解壓即可。解壓完之後包括數據和代碼兩個部分。data文件夾中存放了測試程序用的Mnist數據庫。這裏作者已經將數據庫劃分爲測試樣本集合訓練樣本集,並製作好了對應的標籤矩陣,在調試程序的過程中只需要直接調用數據庫即可,非常方便。以下是需要在debug鏈表中需要加入的opencv的庫,還有其他的路徑這裏不做詳細解釋,可以見:http://blog.csdn.net/vicdd/article/details/52787787


(2)tiny_cnn的基本網絡結構:

         1、Layer_base和Layer:這兩個沒什麼說的,作爲基類,封裝的都是各個層所公有的操作,其內部的功能函數大都是虛函數和純虛函數,依賴子類的多態性實例化。

  2、Input_layer:輸入層,基本的層構造操作,以及前向傳播的的入口和反向傳播的終點,在這一層完成數據(圖像矩陣)的輸入以及前向傳播的開始,同時準備接受反向傳播的結果。

  3、convolutional_layer:卷積層,這是卷積神經網絡的主力層,保存對應的卷積核和偏置核,方便在前向傳播和反向傳播過程中調用計算,同時提供了圖像可視化結構,能夠將保存的權重矩陣轉換爲圖像形式進行可視化輸出。

  4、average_pooling_layer:均值下采樣層,這一層主要有兩個作用,對卷積層的輸出結果進行下采用並可視化輸出。

  5、fully_connected_layer:全連接層,作爲網絡末尾的輸出層,最終的輸出結果就是網絡的最終判決結果,即一個標籤向量,這裏面主要實現了前向傳播算法和反向傳播算法的全連接版(和卷積層略有不同)。

(3)分析程序裏的卷積層-下采樣層-卷積層-下采樣層-卷積層-全連接層模式的CNN結構:

  (1)卷積層C1:輸入圖像的尺寸爲32*32,卷積核尺寸(卷積窗口尺寸)爲5*5,輸入數據模板數量爲1,卷積核模板種類爲6個,導致C1層對每個輸入的圖像進行卷積操作之後,得到6個卷積特徵模板輸出,並且卷積後圖像的尺寸變爲32-5+1=28

  (2)均值下采樣層S2:輸入圖像的尺寸爲28*28,輸入數據矩陣的個數爲6個,均值下采樣是的鄰域窗口爲2*2,。這裏需要強調的一點是S2和C1是相鄰層,S2以C1層的輸出爲輸入,因此S2的輸入尺寸等於C1的輸出尺寸,S2的輸入特徵模板個數等於C1的輸出特徵模板個數,並且這兩層之間的連接方式爲全連接。S2層由於對輸入數據矩陣進行了2*2的均值下采樣,因此導致數據尺寸會縮小爲原來的四分之一,即14*14。

  (3)卷積層C3:輸入圖像尺寸爲14*14,卷積核尺寸爲5*5,輸入數據模板數量爲6個,該層卷積模板種類爲16個,導致C3層對每個輸入的圖像進行卷積操作之後,得到16個卷積特徵模板輸出,並且卷積後圖像的尺寸變爲14-5+1=10。並且C3層與S2層之間的連接屬性並非是默認的全連接,而是按照指定連接方式(存儲在connection變量中)進行連接。

  (4)均值下采樣層S4:輸入數據矩陣的尺寸爲10*10,輸入數據矩陣的個數爲16個,均值下采樣的鄰域窗口爲2*2,與S2相似,這裏的下采樣操作同樣導致矩陣尺寸減半,因此S4層的特徵矩陣輸入尺寸爲5*5。

  (5)卷積層C5:輸入數據矩陣尺寸爲5*5,卷積核尺寸爲5*5,輸入數據模板數量爲16,卷積核模板種類爲120個。由於在這一層數據矩陣的尺寸已經和卷積核尺寸相同,導致每一次的卷積操作都將得到一個具體數值(即卷積窗口無法進行滑動),導致C5層輸出的特徵結構是一個120維的特徵向量。

  (6)全連接層:輸入特徵維數爲120,輸出特徵維數爲10(一共有十類),完成特徵的分類工作,類此與一個抽象的線性分類函數。

  (6)激活函數:從代碼中可以看出,這裏各個層之間的激活函數統一選用tan_h函數,當然tiny_cnn中還封裝了很多其他類型的激活函數,在這裏可以隨便選擇,但需要注意的一點是這個網絡中理論上只能使用一種類型的激活函數。


(4)convolutional_layer類的整體結構

首先介紹在整個網絡裏最重要的一層。

一、成員變量

  convolutional_layer類一共有五個私有的成員變量,in_保存了輸入數據矩陣的基本屬性:行數、列數、維數;out_保存了輸出特徵矩陣的基本形式:函數、列數、維數;weight_保存了權重矩陣的基本形式。connection_保存了當前卷積層與上一層(下采樣層)之間的連接關係,window_size_保存了當前層卷積核尺寸。

  這裏有一點需要強調,in_、out_、weight_三個變量均是index3d<layer_size_t>形式,這裏的index3d實際上指的是一個三元vector類型,其聲明位於util.h文件中:

  所以index3d類型的變量能夠保存三個數值信息,並能夠在其內部做一些簡要運算。

  二、構造函數

  在研究完類的成員變量之後,接下來需要分析其內部的函數實現形式,以求對這個類的功能以及相關結構有更好的理解。convolutional_layer類的成員函數大體上可以分爲三部分:構造函數、層間連接構造函數、返回函數。其中構造函數承擔了成員變量的初始化任務。

  2.1 構造函數的兩種形式

  convolutional_layer類提供了兩種構造函數的形式,一種是採用默認的連接方式,也就是和前一層的卷積輸出進行全連接,定義如下:

  這裏的connection_table()會返回一個默認的全零矩陣,然後init_connection()函數會將默認成員變量connection_初始化爲全零矩陣,全零矩陣也就默認是全連接模式,這點稍後會給出詳細分析。

  convolutional_layer的第二種構造函數需要人爲指定與前一層的連接形式,具體如下:

  這裏connection_table是由外部傳入的、用戶指定的連接矩陣,通過init_connection函數將其賦值給connection_。

  2.2 構造函數輸入參數

  接來下對構造函數的參數以及與基類構造函數的繼承關係進行分析。首先,convolutional_layer類在執行構造時一共需要以下幾個參數: 

  in_width:輸入圖片寬度(矩陣行數);

  in_height:輸入圖片高度(矩陣列數);

  window_size:卷積窗口大小;

  in_channels:輸入的模板數;

  out_channels:輸出的模板數

  connection_table:矩陣的連接形式,可以默認生成也可以用戶指定。

  由於convolutional_layer類是繼承自partial_connected_layer類,因此在執行convolutional_layer構造函數的過程中,首先需要執行其基類partial_connected_layer類的構造函數:

partial_connected_layer<Activation>(in_width * in_height * in_channels, (in_width - window_size + 1) * (in_height - window_size + 1) * out_channels, 
            sqr(window_size) * in_channels * out_channels, out_channels), 

  有關partial_connected_layer類的構造函數我會在介紹partial_connected_layer類的博文中專門進行分析,這裏就先不做過多的表述,接下來需要分析的是在convolutional_layer的構造函數中是如何實現對其成員變量的初始化的,具體代碼如下:

  (1)in_作爲卷積層的輸入參數,直接保存輸入數據矩陣的尺寸以及通道數即可(單通道或者三通道);

  (2)out_作爲卷積層的特徵輸出,由於存在滑動窗口卷積的緣故,導致其輸出的特徵矩陣的尺寸與輸入的數據矩陣的尺寸不一致,具體值爲“in_width - window_size + 1”和“in_height - window_size + 1”,並且輸出的特徵模板數量與指定的out_channels相當。

  (3)weight_作爲卷積層的權重矩陣,其尺寸自然應當和卷積核的尺寸相當,至於個數,則爲輸入數據矩陣數量*輸出特徵模板數量,即每個映射核完成一個輸入矩陣到一個輸出矩陣之間的映射任務,這就是所謂的權值共享和感受野的概念。

  (4)connection_爲卷積網絡與前一層(下采樣層)的連接形式矩陣,保存了表示連接與否標誌位的矩陣,在LeNet-5網絡中,第一個卷積層與輸入層是全連接的,第二個卷積層和下采樣層的連接情況如下所示:

  對應的,在MyTinyCnn的測試程序中給出了對應的定義:

  (5)window_size_保存了當前卷積層卷積核的尺寸,直接由用戶指定即可。

參考:http://blog.csdn.net/u013088062


發佈了11 篇原創文章 · 獲贊 36 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章