Caffe源码(十):eltwise_layer 分析
来源:互联网 发布:情报数据库 编辑:程序博客网 时间:2024/04/28 05:36
目录
- 目录
- 简单介绍
- 主要函数
- LayerSetUp 函数
- Reshape 函数
- Forward_cpu 函数
- Backward_cpu 函数
简单介绍
eltwise_layer 实现多个blobs element-wise 的相加,相乘或者取最大值。
主要函数
1.LayerSetUp 函数:
template <typename Dtype>void EltwiseLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { CHECK(this->layer_param().eltwise_param().coeff_size() == 0 || this->layer_param().eltwise_param().coeff_size() == bottom.size()) << "Eltwise Layer takes one coefficient per bottom blob."; // 如果存在系数,则每个blob 对应一个系数 CHECK(!(this->layer_param().eltwise_param().operation() == EltwiseParameter_EltwiseOp_PROD && this->layer_param().eltwise_param().coeff_size())) << "Eltwise layer only takes coefficients for summation."; op_ = this->layer_param_.eltwise_param().operation();//默认为SUM // Blob-wise coefficients for the elementwise operation. coeffs_ = vector<Dtype>(bottom.size(), 1);//将系数初始化为1 if (this->layer_param().eltwise_param().coeff_size()) { for (int i = 0; i < bottom.size(); ++i) { coeffs_[i] = this->layer_param().eltwise_param().coeff(i); }//coeffs_ 存放从protobuf 传入的每个系数的值 } stable_prod_grad_ = this->layer_param_.eltwise_param().stable_prod_grad();//默认true}
2.Reshape 函数:
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()); }//输入的每个bottom要有相同的shape top[0]->ReshapeLike(*bottom[0]); // 输入和输出的shape相同 // 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());//存放取最大值时的index }}
3.Forward_cpu 函数:
template <typename Dtype>void EltwiseLayer<Dtype>::Forward_cpu( const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) { int* mask = NULL; const Dtype* bottom_data_a = NULL; const Dtype* bottom_data_b = NULL; const int count = top[0]->count(); Dtype* top_data = top[0]->mutable_cpu_data(); switch (op_) { case EltwiseParameter_EltwiseOp_PROD: caffe_mul(count, bottom[0]->cpu_data(), bottom[1]->cpu_data(), top_data); //输出top为输入的两个bottom的element-wise乘积 for (int i = 2; i < bottom.size(); ++i) { caffe_mul(count, top_data, bottom[i]->cpu_data(), top_data); } //将所有输入的bottom做element-wise乘积 break; case EltwiseParameter_EltwiseOp_SUM: caffe_set(count, Dtype(0), top_data); // TODO(shelhamer) does BLAS optimize to sum for coeff = 1? for (int i = 0; i < bottom.size(); ++i) { caffe_axpy(count, coeffs_[i], bottom[i]->cpu_data(), top_data); }// 输出top 为 所有输入bottom乘以对应系数之和 break; case EltwiseParameter_EltwiseOp_MAX: // Initialize mask = max_idx_.mutable_cpu_data(); caffe_set(count, -1, mask);//初始化mask所有elements 为-1 caffe_set(count, Dtype(-FLT_MAX), top_data); // 初始化top所有element 为负无穷 // bottom 0 & 1 bottom_data_a = bottom[0]->cpu_data(); bottom_data_b = bottom[1]->cpu_data(); for (int idx = 0; idx < count; ++idx) { if (bottom_data_a[idx] > bottom_data_b[idx]) { top_data[idx] = bottom_data_a[idx]; // maxval mask[idx] = 0; // maxid } else { top_data[idx] = bottom_data_b[idx]; // maxval mask[idx] = 1; // maxid } }//bottom 0 和bottom 1 做比较 // bottom 2++ for (int blob_idx = 2; blob_idx < bottom.size(); ++blob_idx) { bottom_data_b = bottom[blob_idx]->cpu_data(); for (int idx = 0; idx < count; ++idx) { if (bottom_data_b[idx] > top_data[idx]) { top_data[idx] = bottom_data_b[idx]; // maxval mask[idx] = blob_idx; // maxid 更新为当前最大值的bottom id }// } } break; default: LOG(FATAL) << "Unknown elementwise operation."; }}
4.Backward_cpu 函数:
template <typename Dtype>void EltwiseLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top, const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) { const int* mask = NULL; const int count = top[0]->count(); const Dtype* top_data = top[0]->cpu_data(); const Dtype* top_diff = top[0]->cpu_diff(); for (int i = 0; i < bottom.size(); ++i) { if (propagate_down[i]) { const Dtype* bottom_data = bottom[i]->cpu_data(); Dtype* bottom_diff = bottom[i]->mutable_cpu_diff(); switch (op_) { case EltwiseParameter_EltwiseOp_PROD: if (stable_prod_grad_) { bool initialized = false; for (int j = 0; j < bottom.size(); ++j) { if (i == j) { continue; } if (!initialized) { caffe_copy(count, bottom[j]->cpu_data(), bottom_diff); initialized = true; } else { caffe_mul(count, bottom[j]->cpu_data(), bottom_diff, bottom_diff); }//对于bottom[i]导数为除了自己外输入bottom的element-wise 乘积 } } else {5 caffe_div(count, top_data, bottom_data, bottom_diff); } caffe_mul(count, bottom_diff, top_diff, bottom_diff); //乘以上一层传下来的导数top_diff break; case EltwiseParameter_EltwiseOp_SUM: if (coeffs_[i] == Dtype(1)) { caffe_copy(count, top_diff, bottom_diff); } else { caffe_cpu_scale(count, coeffs_[i], top_diff, bottom_diff); } break; case EltwiseParameter_EltwiseOp_MAX: mask = max_idx_.cpu_data(); for (int index = 0; index < count; ++index) { Dtype gradient = 0; if (mask[index] == i) { gradient += top_diff[index]; } bottom_diff[index] = gradient; }//当该bottom的index值取为最大时,继承top_diff在该index的值,其他位置为0; break; default: LOG(FATAL) << "Unknown elementwise operation."; } } }}
0 0
- Caffe源码(十):eltwise_layer 分析
- Caffe源码(一):math_functions 分析
- Caffe源码(二):blob 分析
- Caffe源码(三):layer 分析
- Caffe源码(四):base_conv_layer 分析
- Caffe源码(五):conv_layer 分析
- Caffe源码(六): pooling_layer 分析
- Caffe源码(八):concat_layer 分析
- Caffe 源码(九):euclidean_loss_layer 分析
- Caffe源码(十一):io.cpp 分析
- Caffe源码(一):math_functions 分析
- Caffe源码(一):math_functions 分析
- Caffe源码(一):math_functions 分析
- Caffe源码(十一):io.cpp 分析
- Caffe 源码(九):euclidean_loss_layer 分析
- Caffe源码(二):blob 分析
- Caffe源码(一):math_functions 分析
- Caffe源码(二):blob 分析
- Linux下添加FTP账号和服务器、增加密码和用户,更改FTP目录
- django框架中使用Python的xlrd和xlwt进行excel表的导入和导出
- map和multimap映射容器
- ulua
- Java程序的三种输入
- Caffe源码(十):eltwise_layer 分析
- 【发极客头条 得C币】人人都是主编!(第1期)
- java Tuple 元组
- 使用百度地图做一个位置选择功能
- Spring 学习笔记(七)——远程服务
- 顷刻天地转:未来还在NUMA上
- MongoDB之聚合
- MBR初识
- C#结构体对象不能为空如何处理