天天看點

Net的網絡層的建構(源碼分析)概述解析網絡檔案建立網絡層确定網絡層需要計算的blob

網絡層的建構是在Net<Dtype>::Init()函數中完成的,建構的流程圖如下所示:

Net的網絡層的建構(源碼分析)概述解析網絡檔案建立網絡層确定網絡層需要計算的blob

從圖中可以看出網絡層的建構分為三個主要部分:解析網絡檔案、開始建立網絡層、網絡層需要參與計算的位置。

該部分主要有兩個函數FilterNet()、InsertSplits()。 

 FilterNet()的作用是模型參數檔案(*.prototxt)中的不符合規則的層去掉。例如:在caffe的examples/mnist中的lenet網絡中,如果隻是用于網絡的前向,則需要将包含train的資料層去掉。 

 InsertSplits()函數的作用是對于底層的一個輸出blob對應多個上層的情況,則要在加入分裂層,形成新的網絡。這麼做的主要原因是多個層反傳給該blob的梯度需要累加。例如:LeNet網絡中的資料層的top label blob對應兩個輸入層,分别是accuracy層和loss層,那麼需要在資料層在插入一層。如下圖:

Net的網絡層的建構(源碼分析)概述解析網絡檔案建立網絡層确定網絡層需要計算的blob

 該部分重要的函數有CreateLayer()、AppendBottom()、AppendTop()、SetUp()。 

 對于CreateLayer()函數,把解析的目前層調用CreatorRegistry類進行注冊,進而擷取到目前層。然後會調用AppendBottom()和AppendTop()函數具體建立層結構。 

對于AppendBottom()函數,其作用是為該層建立bottom blob,由于網絡是堆疊而成,即:目前層的輸出 bottom是前一層的輸出top blob,是以此函數并沒沒有真正的建立blob,隻是在将前一層的指針壓入到了bottom_vecs_中。

 對于AppendBottom()函數,其作用是為該層建立top blob,該函數真正的new的一個blob的對象。并将top blob 的指針壓入到top_vecs_中。經過這兩個函數網絡層建立出該層所有的輸入、輸出blob,接下來就是調用SetUp()函數,正式建立層結構,并為blob配置設定記憶體空間。

 對于SetUp()函數,包含了CheckBlobCounts()、LayerSetUp()、SetLossWeights()、Reshape()等子函數,CheckBlobCounts()函數式讀取Blob的數量,LayerSetUp()和Reshape()是虛函數,會在相應的層中實作這兩個函數,SetLossWeights(top)函數會把top(輸出blob)的loss weight進行初始化,loss weight是用來表示不同Layer産生的loss的重要性,Layer名稱中以Loss結尾表示這是一個會産生loss的Layer,其他的Layer隻是單純的用于中間計算,同時每一層的loss值就是所有輸出top blob的loss值的和。到此目前層的結建構立完成。經過多次循環,就可以建構整個網絡。

該部分的作用是确定哪些層或哪些層的blob需要參與計算,比如前向時需要确定哪些層的blob需要計算loss,後向時确定哪些層的blob需要計算diff。一個layer是否需要backward computation,主要依據兩個方面:

  (1)該layer的top blob 是否參與loss的計算;

  (2)該layer的bottom blob 是否需要backward computation,比如Data層一般就不需要backward computation

對于前向的過程,部分源碼如下: 

 AppendParam()函數的作用是記錄帶有參數的層或者blob,對于某些有參數的層,例如:卷基層、全連接配接層有weight和bias。該函數主要是修改和參數有關的變量,實際的層參數的blob在上面提到的setup()函數中已經建立。對于後向的過程和前向類似,部分源碼如下:

當神已無能為力,那便是魔渡衆生