Eltwise層解析


Concat層雖然利用到了上下文的語義信息,但僅僅是將其拼接起來,之所以能起到效果,在於它在不增加算法復雜度的情形下增加了channel數目。那有沒有直接關聯上下文的語義信息呢?答案是Eltwise層,被廣泛使用,屢試不爽,並且我們常常拿它和Concat比較,所以我常常一起說這兩個層。我們普遍認為,像這樣的“encoder-decoder”的過程,有助於利用較高維度的feature map信息,有利於提高小目標的檢測效果。

Eltwise層有三種類型的操作:product(點乘)、sum(求和)、max(取最大值),顧名思義,sum就是把bottom的對應元素相加,product就是對應相乘,max就是對應取最大,其中sum為默認操作。根據eltwise_layer.cpp的源碼可見,eltwise層要求對應bottom層的blob一致,這才能是對應元素嘛。得到的結果top層的blob和bottom層一致,這個過程想象成三維的過程很好理解。

template <typename Dtype>
void EltwiseLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
      const vector<Blob<Dtype>*>& top) {
  for (int i = 1; i < bottom.size(); ++i) {
    CHECK(bottom[i]->shape() == bottom[0]->shape());
  }
  top[0]->ReshapeLike(*bottom[0]); // If max operation, we will initialize the vector index part.
  if (this->layer_param_.eltwise_param().operation() ==
      EltwiseParameter_EltwiseOp_MAX && top.size() == 1) {
    max_idx_.Reshape(bottom[0]->shape());
  }
}

至於書寫應用格式嘛,看看resnet。

layer {
    bottom: "res2a_branch1"
    bottom: "res2a_branch2c"
    top: "res2a"
    name: "res2a"
    type: "Eltwise"
}
layer {
    bottom: "res5a_branch1"
    bottom: "res5a_branch2c"
    top: "res5a"
    name: "res5a"
    type: "Eltwise"
}

這個書寫的次序可能看着有點不舒服,但不影響使用。上面都是使用的默認sum的Eltwise。

如果需要指定操作,就應該這樣:

layer {
    name: "res2b1"
    type: "Eltwise"
    bottom: "pool1"
    bottom: "res2b1_branch2b"
    top: "res2b1"
    eltwise_param{
        operation:SUM //operation:PROD或者operation:MAX
} }

另外,如果要實現相減,類似也可以實現其它的加權求和或相減,例如:

layer 
{
  name: "res2b1"
  type: "Eltwise"
  bottom: "pool1"
  bottom: "res2b1_branch2b"
  top: "res2b1"
  eltwise_param {
    operation: SUM
    coeff: 1
    coeff: -1
  }
}​

注意coeff參數只對sum起作用,並且有多少個bottom就有多少個coeff。

總結:雖然上面說了這么多,但是sum操作仍然是我們用的最多的。效果上,Eltwise因為更直接的利用了上下文信息,所以精度提高,但是Eltwise的操作卻增加了算法耗時,而Concat層雖然提高的精度沒有Eltwise那么明顯,但是訓練和測試速度相對快了一點,所以應用時更看如何權衡兩者能不能滿足自己項目的需求。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM