閱讀源碼首先要從熟悉目錄結(jié)構(gòu)開始:https://blog.csdn.net/c20081052/article/details/80585888
熟悉完基本目錄結(jié)構(gòu)之后,就要進一步深入學習:https://www.zhihu.com/question/27982282/answer/80242005
源碼閱讀,首先從 src/caffe/proto/caffe.proto開始,了解 對象 和? 磁盤文件的 對應關系。
之后看.hpp文件,理解整個框架,去猜測具體的實現(xiàn),并從基類開始順著 看他的派生類,這樣就會很容易掌握這些類的用法。
再之后,就是針對性的看 cpp 和 cu文件。(一般,是對caffe 進行擴展,繼承現(xiàn)有的類 來實現(xiàn) 新的類。并測試新類的正確性)
再再之后,可以嘗試編寫 各種類工具(如 訓練、測試、特征提取、數(shù)據(jù)轉(zhuǎn)換等工具)
caffe的整個訓練的代碼流程:https://www.cnblogs.com/liuzhongfeng/p/7289956.html
1.學習程序的第一步,先讓程序跑起來,看看結(jié)果,這樣就會有直觀的感受。
Caffe的官網(wǎng)上Caffe | Deep Learning Framework提供了很多的examples,你可以很容易地開始訓練一些已有的經(jīng)典模型,如LeNet。我建議先從LeNet MNIST Tutorial開始,因為數(shù)據(jù)集很小,網(wǎng)絡也很小但很經(jīng)典,用很少的時間就可以跑起來了。當你看到terminal刷拉拉的一行行輸出,看到不斷減少的loss和不斷上升的accuracy,訓練結(jié)束你得到了99+%的準確率,感覺好厲害的樣子。你可以多跑跑幾個例子,熟悉一下環(huán)境和接口。
2.單步調(diào)試,跟著Caffe在網(wǎng)絡里流動
當玩了幾天之后,你對Caffe的接口有點熟悉了,對已有的例子也玩膩了,你開始想看看具體是怎么實現(xiàn)的了。我覺得最好的方法是通過單步調(diào)試的方式跟著程序一步一步的在網(wǎng)絡里前向傳播,然后再被當成誤差信息傳回來。
Caffe就像一個你平常編程中Project,你可以使用IDE或者GDB去調(diào)試它,這里我們不細說調(diào)試的過程。你可以先跟蹤前向傳播的過程,無非就是從高層次到低層次的調(diào)用Forward函數(shù), Solver->Net->Layer->Specific Layer (Convolution等...).后向傳播也類似,但因為你對Caffe里面的各種變量運算不熟悉,當你跟蹤完前向傳播時可能已經(jīng)頭暈眼花了,還是休息一下,消化一下整個前向傳播的流程。
剛剛開始你沒有必要對每個Layer的計算細節(jié)都那么較真,大概知道程序的運算流程就好,這樣你才可以比較快的對Caffe有個大體的把握。
3.個性化定制Caffe
到這里,你已經(jīng)可以說自己有用過Caffe了,但是還不能算入門,因為你還不知道怎么修改源碼,滿足自己特定的需求。我們很多時候都需要自己定義新的層來完成特定的運算,這時你需要在Caffe里添加新的層。
你一開肯定無從下手,腦子一片空白。幸運的是Caffe github上的WikiDevelopment · BVLC/caffe Wiki · GitHub已經(jīng)有了教程了,而且這是最接近latest Caffe的源碼結(jié)構(gòu)的教程,你在網(wǎng)上搜到的Blog很多是有點過時的,因為Caffe最近又重構(gòu)了代碼。你可以跟著它的指導去添加自己的層。
雖然你已經(jīng)知道要在哪里添加自己的東西了,但你遇到最核心的問題是如何寫下面這四個函數(shù)。
forward_cpu()
forward_gpu()
backward_cpu()
backward_gpu()
你可以先模仿已有的層去實現(xiàn)這四個函數(shù),而且我相信forward函數(shù)很快就可以寫出來了,但backward的還是一頭霧水。這時我們就要補補神經(jīng)網(wǎng)絡里最核心的內(nèi)容了——Backpropagation.
4.理解并實現(xiàn)Backpropagation
這個我覺得是與平臺無關的,不管你是使用Caffe、Torch 7,還是Theano,你都需要深刻理解并掌握的。因為我比較笨,花了好長時間才能夠適應推導中的各種符號。其實也不難,就是誤差順著Chain rule法則流回到前面的層。我不打算自己推導后向傳播的過程,因為我知道我沒有辦法將它表達得很好,而且網(wǎng)上已經(jīng)有很多非常好的教程了。下面是我覺得比較好的學習步驟吧。
從淺層的神經(jīng)網(wǎng)絡(所謂的全連接層)的后向傳播開始,因為這個比較簡單,而且現(xiàn)在我們常說的CNN和LSTM的梯度計算也最終會回歸到這里。
第一個必看的是Ng深入淺出的Ufldl教程UFLDL Tutorial,還有中文版的,這對不喜歡看英語的同學是個好消息。當然你看一遍不理解,再看一遍,忘了,再看,讀個幾遍你才會對推導過程和數(shù)學符號熟悉。我頭腦不大行,來來回回看了好多次。
當然,Ufldl的教程有點短,我還發(fā)現(xiàn)了一個講得更細膩清晰的教程,Michael Nielsen寫的Neural networks and deep learning。它講得實在太好了,以至于把我的任督二脈打通了。在Ufldl的基礎上讀這個,你應該可以很快掌握全連接層的反向傳播。
最后在拿出standford大牛karpathy的一篇博客Hacker's guide to Neural Networks,這里用了具體的編程例子手把手教你算梯度,并不是推導后向傳播公式的,是關于通用梯度計算的。用心去體會一下。
這時你躍躍欲試,回去查看Caffe源碼里Convolution層的實現(xiàn),但發(fā)現(xiàn)自己好像沒看懂。雖說卷積層和全連接層的推導大同小異,但思維上還是有個gap的。我建議你先去看看Caffe如何實現(xiàn)卷積的,Caffe作者賈揚清大牛在知乎上的回答在 Caffe 中如何計算卷積?讓我茅塞頓開。重點理解im2col和col2im.
這時你知道了Convolution的前向傳播,還差一點就可以弄明白后向傳播怎么實現(xiàn)了。我建議你死磕Caffe中Convolution層的計算過程,把每一步都搞清楚,經(jīng)過痛苦的過程之后你會對反向傳播有了新的體會的。在這之后,你應該有能力添加自己的層了。再補充一個完整的添加新的層的教程Making a Caffe Layer ? Computer Vision Enthusiast。這篇教程從頭開始實現(xiàn)了一個Angle To Sine Cosine Layer,包含了梯度推導,前向與后向傳播的CPU和GPU函數(shù),非常棒的一個教程。
最后,建議學習一下基本的GPU Cuda編程,雖然Caffe中已經(jīng)把Cuda函數(shù)封裝起來了,用起來很方便,但有時還是需要使用kernel函數(shù)等Cuda接口的函數(shù)。這里有一個入門的視頻教程,講得挺不錯的NVIDIA CUDA初級教程視頻。
caffe源碼閱讀流程補充:
Caffe的代碼結(jié)構(gòu)非常清晰簡單,其實到現(xiàn)在為止,核心代碼4萬行左右。因為我只讀過Caffe的代碼,還評判不了缺點和優(yōu)點。
其主要結(jié)構(gòu)就是:Blob(數(shù)據(jù))和Layer(層)組成Net(網(wǎng)絡),用Slover求解。除了這幾個主要結(jié)構(gòu),其他的除了少量的輔助類,就是大量的具體Layer和Slover的實現(xiàn)(而且基本都是CPU/GPU各一個版本,代碼結(jié)構(gòu)基本一樣,意味著幾乎減少了一小半的代碼量)。
我認為不要開始就讀代碼,先掌握必要的基礎,讀代碼會非常快。我認為從下面幾步開始比較好:
前提:較為不錯的C++水平,不需要C++11。
第一步:弄懂一個簡單的神經(jīng)網(wǎng)絡的訓練過程,比如3層神經(jīng)網(wǎng)絡如何識別手寫數(shù)字這種小項目。有基礎跳過。
第二步:畢竟是讀代碼,所以你要弄明白Caffe的依賴庫都是做什么的,比如glog/gflags/lmdb你得知道有什么用,比較難的是Protocal buffers、CUDA和BLAS,有基礎跳過。
第三步:了解整個項目的結(jié)構(gòu),這個在官網(wǎng)有介紹,其他回答也說的很好。無非是Blob/Layer/Net/Solver幾個主要的類以及輔助類,再就是大量的Layer類的派生。Blob存放數(shù)據(jù)和參數(shù),Layer負責每一層的計算,Net通過創(chuàng)建Blob和Layer構(gòu)建整個網(wǎng)絡,Solver運行求解整個網(wǎng)絡。
第四步:有了上面的幾步,就是閱讀代碼了。先構(gòu)建一個網(wǎng)絡跑通感受下。經(jīng)過第三步你應該知道了主要類的作用,這一步其實就是去尋找這些作用具體實現(xiàn)的代碼,應該不需要很費勁就會把主要的幾個類的代碼看明白。
第五步:各種Layer和Slover的實現(xiàn)。我覺的這部分讀起來最大的問題就是是否掌握了各種層的理論知識。比如你早就掌握了ReLU激活函數(shù),那么relu_layer.hpp/.cpp/.cu這個比較簡單的層也就幾分鐘就看明白。
看的過程中的細節(jié)如果不影響進一步閱讀可以先跳過。
caffe中的設計模式:https://zhuanlan.zhihu.com/p/20456649
在caffe中定義自己的層:
https://zhidao.baidu.com/question/1897850509799556740.html
https://www.huaweicloud.com/articles/c063495c2cedcecd05b40be6ab99ba86.html
https://blog.csdn.net/wanggao_1990/article/details/78863669
https://www.it610.com/article/1306184661927497728.htm
https://blog.csdn.net/kkk584520/article/details/52721838
https://blog.csdn.net/u013289254/article/details/70359995?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-15&spm=1001.2101.3001.4242
https://blog.csdn.net/qq_31347869/article/details/94169967
https://blog.csdn.net/thesby/article/details/50822250
https://support.huaweicloud.com/ti-atc-A800_3000_3010/altasatc_16_020.html
https://www.codenong.com/cs106883615/
http://www.meltycriss.com/2016/07/04/caffe_1_layer/
https://ewenwan.github.io/2018/07/caffe/
https://chaos.blog.csdn.net/article/details/65683988?utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.essearch_pc&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.essearch_pc
通過B站視頻,一些網(wǎng)頁教程,自己練習基本的模型訓練和閱讀代碼之后,最終 還是通過 深度學習 21天實戰(zhàn)Caffe 這本書,得到了進一步的提升。
但是閱讀源碼和編寫單元測試的時候,發(fā)覺,必須對caffe的依賴庫進行學習,才能啃透caffe:
?CUDA:GPU接口(NVIDIA提出的接口)
?BLAS:矩陣運算接口(線性代數(shù)庫)
?ProtoBuff:用于數(shù)據(jù)傳輸?shù)膸欤╣oogle提出的庫)https://developers.google.com/protocol-buffers/docs/overview;https://developers.google.com/protocol-buffers/docs/reference/overview
?Opencv:用于讀取和處理圖像(圖像處理庫)https://docs.opencv.org/ref/2.4.13.6/dc/d8c/namespacecvflann.html
https://www.bilibili.com/video/BV1Q54y1z7kz?from=search&seid=773732718464513168
?Boost:提供 智能指針、計時器、隨機數(shù)產(chǎn)生器等(C++的擴展庫)
?Glog:用于寫日志(google提出的庫)https://github.com/google/glog#id9
?Gflags:用于處理命令行參數(shù)的一個庫 https://gflags.github.io/gflags/
?LevelDB/LMBD:用于存儲數(shù)據(jù)(一個存儲數(shù)據(jù)格式為 key/Value 的數(shù)據(jù)庫)
?Snappy:用于模型參數(shù)和訓練參數(shù)的序列化和反序列化(google提出的一個
壓縮 和 解壓縮庫)
?HDF5:一種數(shù)據(jù)格式
?Gtest:用于進行單元測試(google提出的一個庫)https://google.github.io/googletest/primer.html#simple-tests