[Caffe]:关于Eltwise layer

Eltwise : element-wise

eltwise layer是caffe提供的按元素操作层。它支持3种基本操作:
1. PROD:按元素乘积
2. SUM:按元素求和(默认)
3. MAX:保存元素大者

进行何种操作可以在layer里面通过定义EltwiseOp : x #x:=0,1,2 除此之外,该层还定义了
coeff 参数,该参数只对SUM操作起作用。
最后,caffe还设定了stable_prod_grad #[default = true ] 来选择是否渐进较慢的梯度计算方法,该方法只适用于PROD操作,对SUM操作无效。
更多细节参见下面的源码。

eltwise_layer 源码

#include <cfloat>
#include <vector>#include "caffe/layers/eltwise_layer.hpp"
#include "caffe/util/math_functions.hpp"namespace caffe {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.";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();// Blob-wise coefficients for the elementwise operation.coeffs_ = vector<Dtype>(bottom.size(), 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);}}stable_prod_grad_ = this->layer_param_.eltwise_param().stable_prod_grad();
}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());}
}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_) {                         //choose different operations according to op_case EltwiseParameter_EltwiseOp_PROD:  //PROD,按位乘caffe_mul(count, bottom[0]->cpu_data(), bottom[1]->cpu_data(), top_data);for (int i = 2; i < bottom.size(); ++i) {caffe_mul(count, top_data, bottom[i]->cpu_data(), top_data);}break;case EltwiseParameter_EltwiseOp_SUM: //SUM 按位和,这里有coffs_为系数,可以通过指定某一输入的系数来完成按位加和按位减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);}break;case EltwiseParameter_EltwiseOp_MAX: //按位取大数// Initializemask = max_idx_.mutable_cpu_data();caffe_set(count, -1, mask);caffe_set(count, Dtype(-FLT_MAX), top_data);// bottom 0 & 1bottom_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];  // maxvalmask[idx] = 0;  // maxid} else {top_data[idx] = bottom_data_b[idx];  // maxvalmask[idx] = 1;  // maxid}}// 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];  // maxvalmask[idx] = blob_idx;  // maxid}}}break;default:LOG(FATAL) << "Unknown elementwise operation.";}
}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);}}} else {caffe_div(count, top_data, bottom_data, bottom_diff);}caffe_mul(count, bottom_diff, top_diff, bottom_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;}break;default:LOG(FATAL) << "Unknown elementwise operation.";}}}
}#ifdef CPU_ONLY
STUB_GPU(EltwiseLayer);
#endifINSTANTIATE_CLASS(EltwiseLayer);
REGISTER_LAYER_CLASS(Eltwise);}  // namespace caffe

[Caffe]:关于Eltwise layer相关推荐

  1. Caffe编写Python layer

    Caffe编写Python layer 在使用caffe做训练的时候,通常的做法是把数据转为lmdb格式,然后在train.prototxt中指定,最后在开始训练,转为lmdb格式的优点是读取数据更高 ...

  2. Caffe 增加自定义 Layer 及其 ProtoBuffer 参数

    转载自:http://blog.csdn.net/kkk584520/article/details/52721838 http://blog.csdn.net/kkk584520 博客内容基于新书& ...

  3. caffe中的layer

    layer是神经网络搭建的脚手架,理解了layer,才能盖好神经网络这座摩天大楼. 下图是一张关于layer的思维导图,在功力到达一定程度的时候才可练此功,到时一定会有不一样的收获. 1. Outli ...

  4. caffe源码 layer分析

    Layer 分析 1 layer 总体介绍 2 data 层 3 neuron 层 4 vision 层 5 common层 6 loss层 7 添加自己layer 一.layer总体介绍 1. la ...

  5. caffe data层_Caffe 学习:Eltwise层

    Caffe 学习:Eltwise层 Eltwise层的操作有三个:product(点乘), sum(相加减) 和 max(取大值),其中sum是默认操作. 1. PROD:按元素乘积 2. SUM:按 ...

  6. 梳理caffe代码layer(五)

    Layer(层)是Caffe中最庞大最繁杂的模块.由于Caffe强调模块化设计,因此只允许每个layer完成一类特定的计算,例如convolution操作.pooling.非线性变换.内积运算,以及数 ...

  7. Caffe源码中Pooling Layer文件分析

    Caffe源码(caffe version commit: 09868ac , date: 2015.08.15)中有一些重要的头文件,这里介绍下include/caffe/vision_layers ...

  8. caffe 添加自定义层(custom layer)

    在<剖析Caffe源码之Layer>可以知道layer是所有层的基类,由此类派生出各种不同的不同的层,其如下图所示: 由此扩展出了各种不同的层,基本能满足要求,但是有时候在搭建拓扑网络时, ...

  9. 剖析Caffe源码之Layer

    目录 Layer介绍 Layer分析 LayerParameter Class Layer Layer派生类 Layer源码 Layer构造函数 SetUp函数 Forward函数 Backward函 ...

最新文章

  1. 人事信息管理系统(PMS)
  2. linux 发行版 suse opensuse 区别
  3. 企业网络推广方案分享如何针对大量的长尾词进行更好地优化方法!
  4. 201110阶段二qt事件
  5. 数据结构与算法 | 顺序表
  6. 为什么说减速带是脑残的设计?
  7. 1136 A Delayed Palindrome (20 分)
  8. Sql Server 开窗函数Over()的使用
  9. airpods2怎么查正品 ios11系统_拼多多AirPods2开箱评测,4种办法教你验真假,10个AirPods技巧教你玩...
  10. 一款不错的SpringCloud 脚手架项目
  11. 华为和荣耀蓝牙耳机为什么那么贵?
  12. js php后端 安全,前端JS RSA加密,PHP后端解密实现密码安全传输
  13. 川崎机器人仿真软件K-ROSET破解版的发展历程
  14. 关于Button控件的CommandName属性用法的一个实例
  15. 我眼中 迪杰斯特拉(Dijkstra)与 普雷姆 (prim)的 区别
  16. 极狐GitLab 连接 minikube集群
  17. 推荐一个视频网站-播布客
  18. 美国队长的工资 python代码-Python | 用Python画个美队盾牌送给你
  19. 微信公众号数据2019_2019年微信公众号文章最新数据报告
  20. 前缀学习完结篇 第三课上

热门文章

  1. php自定义扩展函数,Laravel框架中扩展函数、扩展自定义类的方法
  2. api 原生hbase_HBase客户端API
  3. nginx内存占用高---内存池使用思考
  4. 不区分大小写比较Java_java-如何使字符串比较不区分大小写?
  5. python螺旋打印二维数组_Python使用迭代器打印螺旋矩阵的思路及代码示例
  6. jsr 303_使用Spring和JSR 303进行方法参数验证
  7. 计算机应用基础知识点.pdf,《计算机应用基础》复习知识点.pdf
  8. java开发有不加班的吗_8年Java开发的500强企业大佬告诉你,程序员不加班就没有前途吗?...
  9. 渲染测试软件 d15,D5 Render(D5 渲染器)1.7.0 正式版发布 | 一款 RTX 实时光线追踪可视化实时渲染引擎,而且是国产软件!...
  10. chromedp网络监听_动态爬虫三:监听网络事件 + 监听js事件