Caffe源码解读:dropout_layer的正向传播和反向传播

来源:互联网 发布:mysql主键有什么用 编辑:程序博客网 时间:2024/05/18 21:39

原理:

参数:1,神经元被drop out的概率p,被激活的概率为1-p

          2,scale_train_标志位(train过程中被激活的神经元是否乘 1/1-p)

train过程:

          前向传播过程中每个神经元以1-p的概率被激活

          被激活的神经元根据scale_train_标志来确定是否变大1/1-p倍

test过程

            若scale_train_为1,不进行任何处理

            若scale_train_为0,使用“均值网络“,每个神经元的激活值乘(1-p),即缩小

Caffe源码如下

template <typename Dtype>void DropoutLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,      const vector<Blob<Dtype>*>& top) {  NeuronLayer<Dtype>::LayerSetUp(bottom, top);  //读dropout_ratio参数  //每个神经元被激活的概率为1-threshold_  threshold_ = this->layer_param_.dropout_param().dropout_ratio();  DCHECK(threshold_ > 0.);  DCHECK(threshold_ < 1.);  scale_ = 1. / (1. - threshold_);  uint_thres_ = static_cast<unsigned int>(UINT_MAX * threshold_);  scale_train_ = this->layer_param_.dropout_param().scale_train();}template <typename Dtype>void DropoutLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,      const vector<Blob<Dtype>*>& top) {  NeuronLayer<Dtype>::Reshape(bottom, top);  // Set up the cache for random number generation  // ReshapeLike does not work because rand_vec_ is of Dtype uint  // rand_vec_的大小就是bottom[0]的大小  rand_vec_.Reshape(bottom[0]->shape());}
//前向传播template <typename Dtype>void DropoutLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,    const vector<Blob<Dtype>*>& top) {  const Dtype* bottom_data = bottom[0]->cpu_data();  Dtype* top_data = top[0]->mutable_cpu_data();  unsigned int* mask = rand_vec_.mutable_cpu_data();  const int count = bottom[0]->count();  //训练阶段  if (this->phase_ == TRAIN) {    // Create random numbers    // 生成bool随机数,激活神经元所在位置的mask值为1,其余为0    caffe_rng_bernoulli(count, 1. - threshold_, mask);//训练过程中的激活值是否乘scale//关系到测试过程中是否使用“均值网络”    if (scale_train_) {      for (int i = 0; i < count; ++i) {        top_data[i] = bottom_data[i] * mask[i] * scale_;      }    } else {      for (int i = 0; i < count; ++i) {        top_data[i] = bottom_data[i] * mask[i];      }    }  } else {//测试阶段    // 如果scale_train_为1,训练过程中激活神经元的输出乘scale    // 测试过程中,神经元的输出就不用按比例减小了    caffe_copy(bottom[0]->count(), bottom_data, top_data);// 如果scale_train_为0,即训练过程中神经元的输出没有乘scale// 那么测试过程中,神经元的输出除scale    if (!scale_train_) {      caffe_scal<Dtype>(count, 1. / scale_, top_data);    }  }}//反向传播template <typename Dtype>void DropoutLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,    const vector<bool>& propagate_down,    const vector<Blob<Dtype>*>& bottom) {  /*如果进行反向传播*/  if (propagate_down[0]) {    const Dtype* top_diff = top[0]->cpu_diff();    Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();    if (this->phase_ == TRAIN) {      const unsigned int* mask = rand_vec_.cpu_data();      const int count = bottom[0]->count();      if (scale_train_) {        for (int i = 0; i < count; ++i) {          bottom_diff[i] = top_diff[i] * mask[i] * scale_;        }      } else {        for (int i = 0; i < count; ++i) {          bottom_diff[i] = top_diff[i] * mask[i];        }      }    } else {/*反向传播不考虑dropout的情况,直接拷贝数据*/      caffe_copy(top[0]->count(), top_diff, bottom_diff);      if (!scale_train_) {        caffe_scal<Dtype>(top[0]->count(), 1. / scale_, bottom_diff);      }    }  }}


0 0
原创粉丝点击