文章作者:Tyan
博客:noahsnail.com ?|? CSDN ?|? 簡書
Caffe的設計
根據賈揚清的分享整理
Caffe遵循了神經網絡的一個假設:所有的計算都是以layer形式表示的,layer的作用就是根據輸入數據,輸出一些計算以后的結果。以卷積為例,就是輸入一幅圖像,然后與這一層的參數(filter)進行卷積運算,然后輸出卷積的結果。每一個layer需要進行兩種運算:1.forward,從輸入計算輸出;2.backward根據上面的梯度(gradient)來計算相對于輸入的梯度。在每個layer都實現了這兩個函數以后,我們可以將很多層連接成一個網絡,這個網絡做的事情就是輸入我們的數據(圖像或者語音或者whatever),然后來計算我們需要的輸出(比如說識別的label)。在訓練時,我們可以根據已有的label來計算loss和gradient,然后用gradient來update網絡的參數。這個就是Caffe的一個基本流程!
Caffe主要結構
Caffe代碼本身非常模塊化,主要由4部分組成Blob,Layer,Net和Solver。
- Blob
Blob主要用來表示網絡中的數據,包括訓練數據,網絡各層自身的參數,網絡之間傳遞的數據都是通過Blob來實現的,同時Blob數據也支持在CPU與GPU上存儲,能夠在兩者之間做同步。
- Layer
Layer是對神經網絡中各種層的一個抽象,包括卷積層和下采樣層,還有全連接層和各種激活函數層等等。同時每種Layer都實現了前向傳播和反向傳播,并通過Blob來傳遞數據。
- Net
Net是對整個神經網絡的表示,由各種Layer前后連接組合而成,也是我們要構建的網絡模型。
- Solver
Solver定義了針對Net網絡模型的求解方法,記錄神經網絡的訓練過程,保存神經網絡模型參數,中斷并恢復網絡的訓練過程。自定義Solver能夠實現不同的神經網絡求解方式。
Caffe整體架構
Caffe的架構與其它的深度學習框架稍微不同,它沒有根據算法實現過程的方式來進行編碼,而是以系統級的抽象作為整體架構,逐層的封裝實現細節,使得上層的架構變得很清晰。Caffe的整體架構如下:
1. SyncedMem
這個類的主要功能是封裝CPU和GPU的數據交互操作。一般來說,數據的流動形式都是:硬盤->CPU內存->GPU內存->CPU內存->(硬盤),所以在寫代碼的過程中經常會寫CPU/GPU之間數據傳輸的代碼,同時還要維護CPU和GPU兩個處理端的內存指針。這些事情處理起來不會很難,但是會很繁瑣。因此SyncedMem的出現就是把CPU/GPU的數據傳輸操作封裝起來,只需要調用簡單的接口就可以獲得兩個處理端同步后的數據。
2. Blob
Blob是用于存儲數據的對象,在Caffe中各種數據(圖像輸入、模型參數)都是以Blob的形式在網絡中傳輸的,Blob提供統一的存儲操作接口,可用來保存訓練數據、模型參數等,同時Blob還能在CPU和GPU之間進行同步以支持CPU/GPU的混合運算。
這個類做了兩個封裝:一個是操作數據的封裝,使用Blob可以操縱高維的數據,快速訪問其中的數據,變換數據的維度等;另一個是對原始數據和更新量的封裝,每一個Blob中都有data和diff兩個數據指針,data用于存儲原始數據,diff用于存儲反向傳播(Backpropagation)的梯度更新值。Blob使用了SyncedMem,這樣便于訪問不同的處理端。Blob基本實現了整個Caffe數據結構部分的封裝,在Net類中可以看到所有的前后向數據和參數都用Blob來表示就足夠了。數據的抽象到這個就可以了,接下來作層級的抽象。神經網絡的前后向計算可以做到層與層之間完全獨立,只要每個層按照一定的接口規則實現,就可以確保整個網絡的正確性。
3. Layer
Layer是網絡Net的基本單元,也是Caffe中能在外部進行調整的最小網絡結構單元,每個Layer都有輸入Blob和輸出Blob。Layer(層)是Caffe中最龐大最繁雜的模塊,它是神經網絡的基本計算單元。由于Caffe強調模塊化設計,因此只允許每個layer完成一類特定的計算,例如convolution操作、pooling、非線性變換、內積運算,以及數據加載、歸一化和損失計算等。Caffe中layer的種類有很多,具體的種類及功能請看官方文檔。在創建一個Caffe模型的時候,也是以Layer為基礎進行的。Layer是一個父類,它的下面還有各種實現特定功能的子類,例如data_layer,conv_layer,loss_layer等。Layer是通過LayFactory來創建的。
4. Net
Net是一個完整的深度網絡,包含輸入層、隱藏層、輸出層,在Caffe中一般是一個卷積神經網絡(Convolution Neural Networ,CNN)。通過定義不同類型的Layer,并用Blob將不同的Layer連接起來,就能產生一個Net。Net將數據Blob和層Layer組合起來做進一步的封裝,對外提供了初始化和前后傳播的接口,使得整體看上去和一個層的功能類似,但內部的組合可以是多種多樣的。值得一提的是,每一層的輸入輸出數據統一保存在Net中,同時每個層內的參數指針也保存在Net中,不同的層可以通過WeightShare共享相同的參數,因此可以通過配置來實現多個神經網絡層之間共享參數的功能。一個Net由多個Layer組成。一個典型的網絡從data layer(從磁盤中載入數據)出發到loss layer結束。
5. Solver
有了Net就可以進行神經網絡的前后向傳播計算了,但是還缺少神經網絡的訓練和預測功能,Solver類進一步封裝了訓練和預測相關的一些功能。它還提供了兩個接口:一個是更新參數的接口,繼承Solver可以實現不同的參數更新方法,如Momentum,Nesterov,Adagrad等,因此可以使用不同的優化算法。另一個接口是訓練過程中每一輪特定狀態下的可注入的一些回調函數,在代碼中這個回調點的直接使用者就是多GPU訓練算法。Solver定義了針對Net網絡模型的求解方法,記錄網絡的訓練過程,保存網絡模型參數,中斷并恢復網絡的訓練過程。自定義Solver能夠實現不同的神經網絡求解方式。閱讀Solver的代碼可以了解網絡的求解優化過程。Solver是一個父類,它下面還有實現不同優化方法的子類,例如sgd_solver,adagrad_sovler等,Solver是通過SolverFactory來創建的。
6. Proto
caffe.proto位于…/src/caffe/proto目錄下,在這個文件夾下還有一個.pb.cc和一個.pb.h文件,這兩個文件都是由caffe.proto編譯而來的。 在caffe.proto中定義了很多結構化數據,包括:
BlobProto、Datum、FillerParameter、NetParameter、SolverParameter、SolverState、LayerParameter、ConcatParameter、ConvolutionParameter、DataParameter、DropoutParameter、HDF5DataParameter、HDF5OutputParameter、ImageDataParameter、InfogainLossParameter、InnerProductParameter、LRNParameter、MemoryDataParameter、PoolingParameter、PowerParameter、WindowDataParameter、V0LayerParameter。
7. IO
除了上面的東西之外,還需要輸入數據和參數。DataReader和DataTransformer幫助準備輸入數據,Filler對參數進行初始化,一些Snapshot方法可以對模型進行持久化。
參考資料: