建議安裝scitools套裝的understand對(duì)源碼進(jìn)行閱讀凛辣。可以對(duì)整個(gè)工程的代碼進(jìn)行解析后以整個(gè)工程都可以快速地jump to definition相赁。以及可以對(duì)整體代碼進(jìn)行更近一步的解析衷戈。反正無(wú)比好用侨拦,墻裂推薦。
Overview
我們今天主要講一下layers的源碼
layers
我們發(fā)現(xiàn)每一種layer都分成.cpp和.cu兩種赠幕。其實(shí)很好理解俄精,.cpp的是cpu版本的,.cu是cuda版本的榕堰。
我們先來(lái)看看INSTANTIATE_CLASS(ConvolutionLayer);這個(gè)宏操作干了什么
簡(jiǎn)要介紹一下這個(gè)宏操作涉及的##(concatenate)和template specialization.
宏操作##
簡(jiǎn)單來(lái)說(shuō)就是把signal的字符鏈接起來(lái)
舉個(gè)例子
#define cat(a, b) a##b
辣么
printf("%d\n", cat(a,1));
就等價(jià)于
printf("%d\n", a1);
template instantiation
我們使用template的時(shí)候?qū)嶋H上是implicitly實(shí)例化了template的一個(gè)class嘀倒,然而我們也有explicit version.
類似于
template class SampleClass<int>;
注意區(qū)別于template specialization.(模板類/函數(shù)特化是定義在規(guī)定了特定typename的template的定義)
好吧其實(shí)這些都沒(méi)什么卵用。我們其實(shí)更在乎Forward和Backward局冰。
總所周知,CNN主要有一個(gè)end to end的過(guò)程,遵循bp網(wǎng)絡(luò)的定義灌危,有forward也有backward康二。我們來(lái)簡(jiǎn)單看看這個(gè)forward和backward的過(guò)程應(yīng)該怎么寫
CPU version
forward
計(jì)算forward的被分成了兩個(gè)部分。實(shí)際上就是
o = w*i + b
第一部分的w*i對(duì)應(yīng)的就是
this->forward_cpu_gemm(bottom_data + n * this->bottom_dim_,
weight, top_data + n * this->top_dim_);
第二部分(bias)對(duì)應(yīng)的就是
if (this->bias_term_) {
const Dtype* bias = this->blobs_[1]->cpu_data();
this->forward_cpu_bias(top_data + n * this->top_dim_, bias);
}
出于好奇我們?cè)龠M(jìn)一步看看這兩個(gè)函數(shù)是怎么做的
首先介紹一下什么是im2col
http://www.zhihu.com/question/28385679
相當(dāng)于把運(yùn)算分解成兩部勇蝙,首先第一步把矩陣變成一個(gè)一個(gè)的col沫勿,然后再相乘。特別的當(dāng)矩陣是1x1的時(shí)候或者需要skip im2col的時(shí)候(后面一個(gè)什么鬼我還不太清楚味混,總之一般情況下先理解第一個(gè))不需要im2col(廢話)产雹。
為什么要這么做呢?
相當(dāng)于卷積被分解成了
o = col2im(w*im2col(i)) + b)
為什么要這么做呢翁锡?
好求導(dǎo)奥凇!
可以參考
http://zhangliliang.com/2015/02/11/about-caffe-code-convolutional-layer/
(啥時(shí)候才能趕上人家的水平馆衔。瘟判。。角溃。
至于細(xì)節(jié)部分拷获,我想講講我在閱讀中有困難的地方,那就是維數(shù)的問(wèn)題减细。在conv_layer.cpp部分中匆瓜,其實(shí)只是用到了batch_size那一個(gè)維度以及之前和多少個(gè)前面的層連接。沒(méi)有涉及到后面三維ChannelxWeightxHeight未蝌。
而在后面的部分驮吱,使用了im2col把WxH兩個(gè)維度壓成一個(gè)維度V, 于是就有了CxV的一個(gè)矩陣。convolution網(wǎng)絡(luò)層的參數(shù)大小是C_bottom(上一層channel數(shù))xC_top(輸出channel數(shù))树埠,正好對(duì)應(yīng)一個(gè)矩陣乘法糠馆。
接下來(lái)forward部分的代碼屬于很好理解但是文字不好表述的部分(各種offset以及矩陣乘法函數(shù)的各種參數(shù)等等)。所以就不贅述了怎憋。
backward
結(jié)構(gòu)和forward類似又碌。由于backward的原因應(yīng)該考慮top的size九昧。
有了上面所說(shuō)的,其實(shí)這一步也是通過(guò)im2col把卷積變成全連接層的形式毕匀,類似于普通o=ai+b進(jìn)行求導(dǎo)铸鹰。
GPU version
外層的套路和CPU version幾乎是一樣的
Titan X 3000多個(gè)核心呢。皂岔。蹋笼。≡甓猓快得飛起來(lái)剖毯,一般Caffe的網(wǎng)絡(luò)GPU都是CPU的30倍左右。