C++卷積神經網絡實例:tiny_cnn代碼詳解(4)——convolutional_layer類結構信息之成員變量與構造函數


  在之前的博文中我們已經對tiny_cnn框架的整體類結構做了大致分析,闡明了各個類之間的繼承依賴關系,在接下來的幾篇博文中我們將分別對各個類進行更為詳細的分析,明確其內部具體功能實現。在這篇博文中着重分析convolutional_layer類。convolutional_layer封裝的是卷積神經網絡中的卷積層網路結構,其在主程序中對應的初始化部分代碼如下:

  可見在測試程序中我們構建了一個具有五層網絡結構(不包括全連接層)的神經網絡結構,這也正是LeNet-5的結構,在其中一共有三層為卷積層,因此可見卷積層在CNN中所起的重要中用,接下來就從“convolutional_layer<tan_h>(32, 32, 5, 1, 6)”這個代碼入手對convolutional_layer類進行分析。首先給出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_保存了當前卷積層卷積核的尺寸,直接由用戶指定即可。

  OK,這篇博客着重分析了convolutional_layer類中相關的成員變量和構造函數等信息,在下一篇博客中我們將着重對其中的成員函數進行分析,具體說明各個成員變量之間的初始化方式方法。

  三、注意事項

  1、類型別名問題

  在tiny_cnn中,作者通過typedef關鍵字定義了若干類型別名,位於util.h文件中:

  因此在分析代碼的過程中若是遇到這些類型別名,只需知道其真實的類型即可。

  2、代碼截圖問題

  在這系列的博客中,我所分析的很多代碼都是通過截圖的方式來獲得,這樣做的原因有兩個,一是這份tiny_cnn的工程文件大家都可以從網上下載得到,無需再粘貼源碼;二是通過截圖的方式能夠方便對我想要強調的部分進行標記突出,便於大家理解,希望大家習慣這種代碼截圖的方式。不過這種方式也有一個缺點,就是會導致博文的圖片過多,內容過長,大家勉強接受吧。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com