C++卷积神经网络实例:tiny_cnn代码具体解释(7)——fully_connected_layer层结构类分析...
之前的博文中已經(jīng)將卷積層、下採樣層進(jìn)行了分析。在這篇博文中我們對(duì)最后一個(gè)頂層層結(jié)構(gòu)fully_connected_layer類(全連接層)進(jìn)行分析:
一、卷積神經(jīng)網(wǎng)路中的全連接層
在卷積神經(jīng)網(wǎng)絡(luò)中全連接層位于網(wǎng)絡(luò)模型的最后部分,負(fù)責(zé)對(duì)網(wǎng)絡(luò)終于輸出的特征進(jìn)行分類預(yù)測(cè),得出分類結(jié)果:
LeNet-5模型中的全連接層分為全連接和高斯連接,該層的終于輸出結(jié)果即為預(yù)測(cè)標(biāo)簽,比如這里我們須要對(duì)MNIST數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行分類預(yù)測(cè),當(dāng)中的數(shù)據(jù)一共同擁有10類(數(shù)字0~9),因此全全連接層的終于輸出就是一個(gè)10維的預(yù)測(cè)結(jié)果向量,哪一維的值為非零,則預(yù)測(cè)結(jié)果相應(yīng)的就是幾。
二、fully_connected_layer類結(jié)構(gòu)
與之前卷積層和下採樣層不同的是,這里的全連接層fully_connected_layer類繼承自基類layer,當(dāng)中類成員一共可分為四大部分:成員變量、構(gòu)造函數(shù)、前向傳播函數(shù)、反向傳播函數(shù)。
2.1 成員變量
fully_connected_layer類的成員變量?jī)H僅有一個(gè)。就是一個(gè)Filter類型的變量:
而這里的Filter是通過類模板參數(shù)傳入的一個(gè)缺省filter_none類型,具體例如以下:
至于filter_none類型,從名稱推斷應(yīng)該是一個(gè)和濾波器核相關(guān)的類封裝,具體定義在dropout.h文件里:
有關(guān)dropout.h文件里封裝的相關(guān)類的具體信息我會(huì)在之后的博文中進(jìn)行具體的介紹。這里先留一個(gè)坑,只是事先透漏一點(diǎn),卷積神經(jīng)網(wǎng)絡(luò)中的dropout本質(zhì)上是為了改善網(wǎng)絡(luò)過擬合性能而設(shè)計(jì)的。
2.2 構(gòu)造函數(shù)
構(gòu)造函數(shù)極其簡(jiǎn)單。單純的調(diào)用了基類layer的構(gòu)造函數(shù):
至于基類layer,里面封裝了大量的虛函數(shù)以及純虛函數(shù),并給出了網(wǎng)絡(luò)層主要的框架設(shè)定。對(duì)layer_base類進(jìn)行了一部分實(shí)例化,這幾點(diǎn)我們以后會(huì)具體說的。
2.3 前向傳播函數(shù)
眾所周知,卷積神經(jīng)網(wǎng)絡(luò)在訓(xùn)練時(shí)和BP神經(jīng)網(wǎng)絡(luò)的訓(xùn)練極其類似。包含一個(gè)樣本預(yù)測(cè)的前向傳播過程和誤差的反向傳播過程。
首先前向傳播函數(shù)的代碼例如以下:
const vec_t& forward_propagation(const vec_t& in, size_t index) {vec_t &a = a_[index];vec_t &out = output_[index];for_i(parallelize_, out_size_, [&](int i) {a[i] = 0.0;for (int c = 0; c < in_size_; c++)a[i] += W_[c*out_size_ + i] * in[c];a[i] += b_[i];});for_i(parallelize_, out_size_, [&](int i) {out[i] = h_.f(a, i);});auto& this_out = filter_.filter_fprop(out, index);return next_ ?next_->forward_propagation(this_out, index) : this_out; }
從代碼中能夠看出這個(gè)前向傳播函數(shù)本質(zhì)上屬于一個(gè)遞歸函數(shù),用遞歸的方式實(shí)現(xiàn)層層傳播的功能:
在前向傳播的過程中,主要有兩個(gè)階段。一是通過當(dāng)前層的卷積核和偏置完畢對(duì)輸入數(shù)據(jù)的映射:
從代碼中可見,卷積層的映射過程本質(zhì)上就是一個(gè)卷積操作,然后在對(duì)卷積結(jié)果累加偏置。第二個(gè)階段就是將卷積層的映射結(jié)果送入激活函數(shù)中進(jìn)行處理:
激活函數(shù)的主要作用是對(duì)卷積層的映射輸出進(jìn)行規(guī)范化。調(diào)整期數(shù)據(jù)分布。經(jīng)典的激活函數(shù)是Sigmoid函數(shù)。主要對(duì)輸出特征進(jìn)行平滑。在之后學(xué)者又提出Relu類型的激活函數(shù)。主要是對(duì)輸出特征進(jìn)行稀疏化規(guī)范,使其更接近于人腦的視覺映射機(jī)理。在tiny_cnn中作者封裝了sigmoid、relu、leaky_relu、softmax、tan_h、tan_hp1m2等激活函數(shù),這些類都定義在activation命名空間中,具體在activation_function.h文件里,在興許的篇幅中我會(huì)專門拿出一篇博文的篇幅對(duì)tiny_cnn的激活函數(shù)做集中的分析。
2.4 反向傳播函數(shù)
反向傳播算法是BP類型神經(jīng)網(wǎng)絡(luò)的經(jīng)典特征。大部分都採用隨機(jī)梯度下降法對(duì)誤差進(jìn)行求導(dǎo)和傳播。因?yàn)榉聪騻鞑ニ惴ㄉ婕暗秸`差的求偏導(dǎo)、靈敏度傳遞等概念,導(dǎo)致其在原理上相對(duì)于前向傳播過程顯得更為復(fù)雜,代碼實(shí)現(xiàn)也較為繁瑣。我們這里僅僅是先給出反向傳播的代碼,在興許的博文中在針對(duì)這個(gè)傳播過程進(jìn)行更文具體的分析。OK,又是一個(gè)坑:
const vec_t& back_propagation(const vec_t& current_delta, size_t index) {const vec_t& curr_delta = filter_.filter_bprop(current_delta, index);const vec_t& prev_out = prev_->output(index);const activation::function& prev_h = prev_->activation_function();vec_t& prev_delta = prev_delta_[index];vec_t& dW = dW_[index];vec_t& db = db_[index];for (int c = 0; c < this->in_size_; c++) {// propagate delta to previous layer// prev_delta[c] += current_delta[r] * W_[c * out_size_ + r]prev_delta[c] = vectorize::dot(&curr_delta[0], &W_[c*out_size_], out_size_);prev_delta[c] *= prev_h.df(prev_out[c]);}for_(parallelize_, 0, out_size_, [&](const blocked_range& r) {// accumulate weight-step using delta// dW[c * out_size + i] += current_delta[i] * prev_out[c]for (int c = 0; c < in_size_; c++)vectorize::muladd(&curr_delta[0], prev_out[c], r.end() - r.begin(), &dW[c*out_size_ + r.begin()]);for (int i = r.begin(); i < r.end(); i++) db[i] += curr_delta[i];});return prev_->back_propagation(prev_delta_[index], index);}四、注意事項(xiàng)
1、卷積層和下採樣層的前向/反向傳播函數(shù)
在fully_connected_layer類中我們發(fā)現(xiàn)其內(nèi)部封裝了前向/反向傳播函數(shù),但在之前介紹的卷積層和均值下採樣層中我們并沒有發(fā)現(xiàn)前向/反向傳播函數(shù)的影子,但前向/反向傳播函數(shù)確實(shí)是一個(gè)全局的過程。不可能出現(xiàn)斷層,因此細(xì)致研究就會(huì)發(fā)現(xiàn)原來作者是將convolutional_layer類和average_pooling_layer相應(yīng)的前向/反向傳播函數(shù)封裝在了它們共同的基類:partial_connected_layer中了。
2、前向傳播函數(shù)和反向傳播函數(shù)
在這篇博文中我為興許的博文中挖下了非常多大坑,尤其像前向/反向傳播函數(shù)這樣的卷積神經(jīng)網(wǎng)絡(luò)訓(xùn)練的精華部分,是最能體現(xiàn)作者編程功力和框架設(shè)計(jì)功力的地方,一兩篇博文都不一定能講的清楚,所以請(qǐng)大家不要著急,我會(huì)盡快把當(dāng)中的玄機(jī)弄明確。然后用通俗的語言進(jìn)行解釋的,所以說??右欢〞?huì)都一一填上的。
轉(zhuǎn)載于:https://www.cnblogs.com/yangykaifa/p/7222179.html
總結(jié)
以上是生活随笔為你收集整理的C++卷积神经网络实例:tiny_cnn代码具体解释(7)——fully_connected_layer层结构类分析...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php-URL方法下载远程图片
- 下一篇: 如何实现文字在图片中间的效果