ParseNet和部分文章中提到在進行feature fusion之前要進行 L2norm,這是因為多層feature map的啟用值大小分布差距比較大,如果沒有經過 norm,會導致啟用值普遍較大的 feature map 對融合後的結果影響更大。 簡介 L2norm公式
L2norm反向傳播BP推導
L2norm的caffe實現
但是網上很難找到 L2norm 相關的源碼,caffe本身也沒有實現,大致看了一下github上有很多關於 L2norm 的實現也不夠完善,比如並沒有提供 across spatial: false/ true 兩種不同的模式,經過搜尋,發現實際上 ParseNet 的作者Wei Liu大神在自己的Github上放出了L2norm的官方源碼,只是命名和存放位置不太好找。
Wei Liu大神實現的L2norm源碼可以見這裡,其命名為normalize_layer,對應的 .cpp, .cu, .hpp 檔案都可以在對應的位置找到。另外由於Wei Liu大神的 SSD 文章中也用到了 L2norm,因此可以在 SSD 的 prototxt 中找到noramlize_layer的使用範例,見這裡。 源碼分析 caffe.proto分析
message NormalizeParameter { optional bool across_spatial = 1 [default = true]; // Initial value of scale. Default is 1.0 for all optional FillerParameter scale_filler = 2; // Whether or not scale parameters are shared across channels. optional bool channel_shared = 3 [default = true]; // Epsilon for not dividing by zero while normalizing variance optional float eps = 4 [default = 1e-10]; }
這裡面有兩個很重要的參數,across_spatial和channel_shared。 accross_spatial決定了normalization的範圍,如果為true的話(預設),則對每個num(channel*height*width)整體進行normalization,也就是上面xi的平方加和的個數是channel*height*width;如果是false的話,就表明normalization不是accross_spatial的,上面加和的個數是channel,也就是說,spatial中的每個像素點(height*width個數)分別進行normalization,這就大大減小了normalization的範圍。 channel_shared: 在上面的歸一化完了之後,要將top_data乘以一個scale(這個scale是normalization_layer的唯一的參數),如果channel_shared為true(預設),那麼top_data的所有channel都乘以同一個數,如果channel_shared為false,那麼top_data的channel乘的數是不一樣的。
至於其他的cpp,cu檔案實現細節可以自己去看,也可以見參考1和參考2。 使用小結
最近花了倆星期對Layer Norm, Instance Norm, L2norm, Local Response Norm, Group Norm在feature fusion中的使用,總起來說,效果都不好,而且感覺norm後scale層初始化參數的設定對結果影響非常大,很難調,基本算是複現失敗了,還不如單純使用eltwise sum或者 concatenation 不加任何norm直接融合多個特徵圖的效果。有做出來的大神不妨在評論中指點一下,或者大家之間互相多交流也不錯。