0

我想在Caffe樣式構建L2範數層(好吧,其實我是想在pycaffe層使用Tensorflow,因爲使用CUDA.cu文件復路Caffe是一項繁重的任務)Tensorflow,我如何可以計算給定進功能

直傳:
- 輸入(X):ND陣列
- 輸出(Y):ND陣列,其具有輸入
的相同的形狀 - 操作:

y = x/sqrt(sum(x^2,axis=(0,1))) # channel wise L2 normalization 

class L2NormLayer: 
    def __init__(self): 
     self.eps = 1e-12 
     self.sess = tf.Session() 

    def forward(self, in_x): 
     self.x = tf.constant(in_x) 
     self.xp2 = tf.pow(self.x, 2) 
     self.sum_xp2 = tf.reduce_sum(self.xp2, axis=(0, 1)) 
     self.sqrt_sum_xp2 = tf.sqrt(self.sum_xp2 + self.eps) 
     self.hat = tf.div(self.x, self.sqrt_sum_xp2) 

     return self.sess.run(self.hat) 

    def backward(self, dl): 
     # 'dl' is loss calculated at upper layer (chain rule) 
     # how do I calculate this gradient automatically using Tensorflow 

     # hand-craft backward version 
     loss = tf.constant(dl) 
     d_x1 = tf.div(loss, self.sqrt_sum_xp2) 
     d_sqrt_sum_xp2 = tf.div(-tf.reduce_sum(self.x * dl, axis=(0, 1)), (self.eps + tf.pow(self.sqrt_sum_xp2, 2))) 
     d_sum_xp2 = tf.div(d_sqrt_sum_xp2, (self.eps + 2 * tf.sqrt(self.sum_xp2))) 
     d_xp2 = tf.ones_like(self.xp2) * d_sum_xp2 
     d_x2 = 2 * self.x * d_xp2 
     d_x = d_x1 + d_x2 

     return self.sess.run(d_x) 

如在代碼註釋,我怎樣才能calcualte直傳函數的通過自動使用Tensorflow梯度?

回答

1

我認爲你最好的策略是使用現有的咖啡層來實現你的目標。
首先,使用"Reduction"層來計算平方x L2範數:

layer { 
    name: "norm_x_sq" 
    type: "Reduction" 
    bottom: "x" 
    top: "norm_x_sq" 
    reduction_param { operation: SUMSQ axis: 1 } 
} 

使用"Power"層採取規範的平方根計算它的倒數:

layer { 
    name: "norm_x-1" 
    type: "Power" 
    bottom: "norm_x_sq" 
    top: "norm_x-1" 
    power_param { power: -0.5 } 
} 

一旦你有分母,你需要"Tile"回到相同shapex

layer { 
    name: "denom" 
    type: "Tile" 
    bottom: "norm_x-1" 
    top: "denom" 
    tile_param { axis:1 tiles: N } # here you'll have to manually put the target dimension N 
} 

最後,使用"Eltwise"層標準化x

layer { 
    name: "x_norm" 
    type: "Eltwise" 
    bottom: "x" 
    bottom: "denom" 
    top: "x_norm" 
    eltwise_param { operation: PROD } 
} 

一些其他注意事項:
1.規範劃分可能是數值不穩定若範是非常小的。在考慮平方根的倒數之前,您可能需要考慮在"norm_x_sq"中添加一個微小的常數。您也可以使用現有圖層來做到這一點。
2.本示例顯示瞭如何根據axis=1維度進行歸一化。根據向量在blob中的排列方式,您可以使用"Scale"圖層來代替tile + eltwise。
3.您可能還會發現this thread有用。

+1

嗨@Shai,謝謝你的整潔解決方案。這是我目前最有效的解決方案。我會盡力盡快部署。但是,我正在尋求一種更通用的方法來在我自己的層中啓用GPU。使用caffe的內建層的問題之一是我的功能不能太複雜,例如需要選擇滿足特定條件的元素的定製激活層。因此,我正在尋找一種方法來在我的pycaffe層中利用Tensorflow的自動漸變功能。 – Microos

+0

我注意到你的實現和我的有一些區別。減少給出了一個形狀(1,0,0,0)的結果,但是,我想只有通道方式的L2,它可以給出形狀(0,0,W,H)的結果。 – Microos