有多个分支时,caffe如何计算梯度?

时间:2019-03-19 17:43:54

标签: machine-learning optimization deep-learning gradient caffe

我正在阅读Caffe的源代码,然后我想到了这个问题。

caffe/relu_layer.cpp为例。在计算梯度时,

void ReLULayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
    const vector<bool>& propagate_down,
    const vector<Blob<Dtype>*>& bottom) {
  if (propagate_down[0]) {
    const Dtype* bottom_data = bottom[0]->cpu_data();
    const Dtype* top_diff = top[0]->cpu_diff();
    Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
    const int count = bottom[0]->count();
    Dtype negative_slope = this->layer_param_.relu_param().negative_slope();
    for (int i = 0; i < count; ++i) {
      bottom_diff[i] = top_diff[i] * ((bottom_data[i] > 0)
          + negative_slope * (bottom_data[i] <= 0));
    }
  }
}

我们可以看到最终为bottom_diff分配了一个值,表明该值是相应底部斑点的梯度。

但是,当多层将一个斑点作为输入时,例如,在一个斑点上堆叠多个ReLU层,Caffe如何处理梯度计算?第一层ReLU修改了bottom_diff,第二层ReLU似乎只是对其进行了覆盖,而不是添加两个渐变。

我没看到任何地方进行梯度求和,这让我感到困惑。如果我错过了重要的事情,请告知我,非常感谢。

1 个答案:

答案 0 :(得分:0)

在多个底部使用顶部斑点时,Caffe自动插入“分割”层。这是在Net<Dtype>::Init(...)内部通过从InsertSplits(...)调用caffe/utils/insert_splits.cpp来完成的。

示例:

protobuf对象NetParameter中的原始网络(此处的节点为层):

data ---> conv1 -> conv2 -> ...
      \-> somelayer -> ...
Net之后,在内存中有

LayerNet::Init()

data -> split ---> conv1 -> conv2 -> ...
               \-> somelayer -> ...

(一个有趣的细节,顺便说一下:.diff分配了激活Blobs中的Backward(),而{{ 1}}。)