caffe框架分析

一、總體流程

caffe主要有四個功能模塊。

a) ?Blob 主要用來表示網絡中的數據,包括訓練數據,網絡各層自身的參數(包括權值、偏置以及它們的梯度),網絡之間傳遞的數據都是通過 Blob 來實現的,同時 Blob 數據也支持在 CPU 與 GPU 上存儲,能夠在兩者之間做同步。

b) ?Layer 是對神經網絡中各種層的一個抽象,包括我們熟知的卷積層和下采樣層,還有全連接層和各種激活函數層等等。同時每種 Layer 都實現了前向傳播和反向傳播,并通過 Blob 來傳遞數據。

c) Net 是對整個網絡的表示,由各種 Layer 前后連接組合而成,也是我們所構建的網絡模型。

d) Solver 定義了針對 Net 網絡模型的求解方法,記錄網絡的訓練過程,保存網絡模型參數,中斷并恢復網絡的訓練過程。自定義 Solver 能夠實現不同的網絡求解方式。

整體的框架是以layer為主,不同的layer完成不同的功能,如卷積,反卷積等。net是管理layer的,solver是做訓練用的,而核心的創新就是blob數據了,以一個四元組完成了各種數據的傳輸,同時解決了cpu和gpu共享數據的問題。


二. 卷積操作

對圖像(不同的數據窗口數據)和濾波矩陣(一組固定的權重:因為每個神經元的多個權重固定,所以又可以看做一個恒定的濾波器filter)做內積(逐個元素相乘再求和)的操作就是所謂的『卷積』操作,也是卷積神經網絡的名字來源。


? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(上圖可以看作一個濾波器filter,多個filter構成一個卷積層)


上圖中有兩個卷積核(filter w0和w1),每個卷積核有三個通道(channels),每個filter的值就是權重值,我們要求的就是改變里面的值使損失函數最小。


3. caffe中的數學函數

A) ?caffe_cpu_gemm 函數:

void caffe_cpu_gemm(const CBLAS_TRANSPOSE TransA, const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const float alpha, const float* A, const float* B, const float beta, float* C)

功能: C=alpha*A*B+beta*C

A,B,C 是輸入矩陣(一維數組格式)

CblasRowMajor :數據是行主序的(二維數據也是用一維數組儲存的)

TransA, TransB:是否要對A和B做轉置操作(CblasTrans CblasNoTrans)

M: A、C 的行數

N: B、C 的列數

K: A 的列數, B 的行數

lda : A的列數(不做轉置)行數(做轉置)

ldb: B的列數(不做轉置)行數(做轉置)

這個函數主要是用了庫函數的運算公式進行矩陣相乘,那接下來就是怎么將卷積運算轉化為矩陣相乘的問題了,這就需要用到image2col的函數了。

B) image2col 函數:




? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?最終:Filter Matrix乘以Feature Matrix,得到輸出矩陣Cout x (H x W)。




再說的詳細點:




如上圖

(1)在矩陣A中

M為卷積核個數,K=k*k,等于卷積核大小,即第一個矩陣每行為一個卷積核向量(是將二維的卷積核轉化為一維),總共有M行,表示有M個卷積核。

(2)在矩陣B中

因此,N為輸出圖像大小的長寬乘積,也是卷積核在輸入圖像上滑動可截取的最大特征數。

K=k*k,表示利用卷積核大小的框在輸入圖像上滑動所截取的數據大小,與卷積核大小一樣大。

(3)在矩陣C中

矩陣C為矩陣A和矩陣B相乘的結果,得到一個M*N的矩陣,其中每行表示一個輸出圖像即feature map,共有M個輸出圖像(輸出圖像數目等于卷積核數目)

Caffe中的卷積計算是將卷積核矩陣和輸入圖像矩陣變換為兩個大的矩陣A與B,然后A與B進行矩陣相乘得到結果C。


C)im2col_cpu分析

1.結合代碼分析以下公式的由來

int output_h = (height + 2 * pad_h -? (dilation_h * (kernel_h - 1) + 1)) / stride_h + 1;

int output_w = (width + 2 * pad_w -(dilation_w * (kernel_w - 1) + 1)) / stride_w +1;

2.先不要dilation_h 和dilation_w ,如下:

N=((image_h + 2*pad_h – kernel_h)/stride_h+ 1)*((image_w +2*pad_w – kernel_w)/stride_w + 1)

這里要結合動態stride滑動卷積圖

原理: N = H*W

H:? 在image高度方向上滑動的總次數。W:在image寬度方向上滑動的次數


D)Dilation分析

1.由于池化層的存在,響應張量的大小(長和寬)越來越小。

2.池化層去掉隨之帶來的是網絡各層的感受野(receptive field)變小,這樣會降低整個模型的預測精度。

3. Dilated convolution 的主要貢獻就是,如何在去掉池化下采樣操作的同時,而不降低網絡的感受野。


結合這個圖再推倒一下output_h 和output_w的公式

Dilation :表示每個元素的相隔距離,如果相鄰,dilation=1

運算公式: (除去原點的長度)×dilation(擴張系數)+ 1(原點)

即: kernel_h_new = (kernel_h-1)*dilation_h +1

kernel_w_new = (kernel_w-1)*dilation_w +1


E)im2col_cpu整體分析



F)Forward_cpu的整體分析

1. forward_cpu_gemm:

這個主要是處理處理Wx 的函數,里面分為兩個步驟:

a)conv_im2col_cpu:將image轉為矩陣

?b) caffe_cpu_gemm: 將A中的矩陣和卷積核的矩陣相乘,得到特征圖像的矩陣。

2. forward_cpu_bias:

這個主要是處理偏置數據。

G)Conv_layer的整體分析

1. Forward_cpu

2. Backward_cpu

F)BP流程

Backward_cpu函數的代碼,整個更新過程大概可以分成三步

1. caffe_cpu_gemm(CblasTrans, CblasNoTrans, N_, K_, M_, (Dtype)1., top_diff, bottom_data, (Dtype)1., this->blobs_[0]->mutable_cpu_diff());


其中的bottom_data對應的是a,即輸入的神經元激活值,維數為K_×N_,top_diff對應的是delta,維數是M_×N_,而caffe_cpu_gemm函數是對blas中的函數進行封裝,實現了一個N_×M_的矩陣與一個M_×K_的矩陣相乘(注意此處乘之前對top_diff進行了轉置)。相乘得到的結果保存于blobs_[0]->mutable_cpu_diff(),對應dW。

2. caffe_cpu_gemv(CblasTrans, M_, N_, (Dtype)1., top_diff, bias_multiplier_.cpu_data(), (Dtype)1., this->blobs_[1]->mutable_cpu_diff());


caffe_cpu_gemv函數實現了一個M_×N_的矩陣與N_×1的向量進行乘積,其實主要實現的是對delta進行了一下轉置,就得到了db的值,保存于blobs_[1]->mutable_cpu_diff()中。此處的與bias_multiplier_.cpu_data()相乘是實現對M_個樣本求和,bias_multiplier_.cpu_data()是全1向量,從公式上看應該是取平均的,但是從loss傳過來時已經取過平均了,此處直接求和即可。

3.3 . caffe_cpu_gemm(CblasNoTrans, CblasNoTrans, M_, K_, N_, (Dtype)1., top_diff, this->blobs_[0]->cpu_data(), (Dtype)1., bottom[0]->mutable_cpu_diff());



主要Inner_product層里面并沒有激活函數,因此沒有乘f’,與f’的相乘寫在ReLU層的Backward函數里了,因此這一句里只有W和delta_l+1相乘。blobs_[0]->cpu_data()對應W,維度是N_×K_,bottom[0]->mutable_cpu_diff()是本層的delta_l,維度是M_×K_。

caffe里的反向傳播過程只是計算每層的梯度的導,把所有層都計算完之后,在solver.cpp里面統一對整個網絡進行更新。


? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 先寫到這里吧,學無止境,且學且記錄。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? END

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容