Caffe_Activation

一般来说,激励层的输入输出尺寸一致,为非线性函数,完成非线性映射,从而能够拟合更为复杂的函数表达式激励层都派生于NeuronLayer: class XXXlayer : public NeuronLayer

1.基本函数

激励层的基本函数较为简单,主要包含构造函数和前向、后向函数

  explicit XXXLayer(const LayerParameter& param)
:NeuronLayer<Dtype>(param){}
virtual inline const char* type() const { return "layerNane"; }
virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top);
virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
const vector<Blob<Dtype>*>& top);
virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);

2.常用激励函数

(1) Relu/PRelu Rectufied Linear Units

ReLU的函数表达式为\(f(x) = x*(x>0) + negative\_slope*x*(x <= 0)\) 具体实现如下

  //forward_cpu
template <typename Dtype>
void ReLULayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
vector<Blob<Dtype>*>& top){ // 根据bottom求解top
const Dtype* bottom_data = bottom[0]->cpu_data();//const 不可修饰
Dtype* top_data = top[0]->mutable_cpu_data();//可修饰
const int count = bottom[0]->count();//因为count_一致,也可用top
Dtype negative_slope = this->layer_param_.relu_param().negative_slope();
for (size_t i = 0; i < count; i++) {
top_data[i] = bottom_data[i]*(bottom_data[i] > 0)
+ negative_slope*bottom_data[i]*(bottom_data[i] <= 0);
}
} //Backward_cpu
// 导数形式 f'(x) = 1 x>0 ; negative_slope*x x<0
template <typename Dtype>
void ReLULayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,const vector<Blob<Dtype>*>& bottom){
const Dtype* top_diff = top[0].cpu_diff();//top diff
const Dtype* bottom_data = bottom[0].cpu_data();//用以判断x是否大于0
Dtype* bottom_diff = bottom[0].cpu_diff();//bottom diff
const int count = bottom[0].count();
for (size_t i = 0; i < count; i++) {
bottom_diff[i] = top_diff[i]*(bottom_data[i] > 0)
+negative_slope*(bottom_data[i] <= 0);
}
} // Relu 函数形式简单,导函数简单,能有效的解决梯度弥散问题,但是当x小于0时,易碎
// 但是网络多为多神经元,所以实际应用中不会影响到网络的正常训练。
(2) Sigmoid (S曲线)

Sigmoid函数表达式为\(f(x) = 1./(1+exp(-x))\);值域0-1,常作为BP神经网络的激活函数

由于输出为0-1,也作为logistic回归分析的概率输出函数。具体实现如下;


//定义一个sigmoid函数方便计算
template <typename Dtype>
inline Dtype sigmoid(Dtype x){
return 1./(1.+exp(-x));
}
//前向 直接带入sigmoid函数即可
template <typename Dtype>
void SigmoidLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
vector<Blob<Dtype>*>& top){
const Dtype* bottom_data = bottom[0]->cpu_data();
Dtype* top_data = top[0]->mutable_cpu_data();//需要计算
const int count = bottom[0]->count();//N*C*H*W;
for (size_t i = 0; i < count; i++) {
top_data[i] = sigmoid(bottom_data[i]);
}
} //Backward_cpu 由于f'(x) = f(x)*(1-f(x)),所以需要top_data
// bottom_diff = top_diff*f'(bottom_data) = top_diff*top_data*(1-top_data)
template <typename Dtype>
void SigmoidLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,vector<Blob<Dtype>*>& bottom){
const Dtype* top_diff = top[0]->cpu_diff();
const Dtype* top_data = top[0]->cpu_data();
Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); //需要计算
const int count = bottom[0]->count();
for (size_t i = 0; i < count; i++) {
//top_data[i] == sigmoid(bottom_data[i]);
bottom_diff[i] = top_diff[i]*top_data[i]*(1.-top_data[i]);
}
} // Sigmoid函数可以作为二分类的概率输出,也可以作为激活函数完成非线性映射,但是网络
// 增加时,容易出现梯度弥散问题,目前在CNN中基本不使用

(3)TanH,双正切函数

TanH函数的表达式为 \(\frac{(1.-exp(-2x))}{(1.+exp(-2x))}\);值域0-1,与sigmoid函数有相同的问题,

但是TanH在RNN中使用较为广泛,理由参考,具体实现如下所示。

    //定义一个tanH的函数表达式,实际已经封装
inline Dtype TanH(Dtype x){
return (1.-exp(-2*x))/(1.+exp(-2*x));
} //Forward_cpu
template <typename Dtype>
void TanHLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
vector<Blob<Dtype>*>& top){
const Dtype* bottom_data = bottom[0]->cpu_data();
Dtype* top_data = top[0]->mutable_cpu_data();
const int count = bottom[0]->count();
for (size_t i = 0; i < count; i++) {
top[i] = TanH(bottom_data[i]);
}
} //Backward_cpu f'(x) = 1-f(x)*f(x);
// bottom_diff = top_diff(1-top_data*top_data);
template <typename Dtype>
void TanHLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
const vector<bool>& propagate_down,vector<Blob<Dtype>*>& bottom){
const Dtype* top_diff = top[0]->cpu_diff();
const Dtype* top_data = top[0]->cpu_data();
Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); //需要计算
const int count = bottom[0]->count();
for (size_t i = 0; i < count; i++) {
//top_data[i] == TanH(bottom_data[i]);
bottom_diff[i] = top_diff[i]*(1.-top_data[i]*top_data[i]);
}
}
其他的激励函数就不在枚举,可以查看具体的caffe源码,实现大致相同

3.说明

(1) 梯度弥散和梯度爆炸

网络方向传播时,loss经过激励函数会有\(loss*\partial{f(x)}\),而如sigmoid的函数,

max(\(\partial{f(x)}\))只有1/4因此深层网络传播时loss越来越小,则出现前层网络未完整学习而后层网络学习饱和的现象

(2) Caffe激励层的构建

如上述的代码所示,激励层主要完成forward和Bacward的函数实现即可,由构建的函数表达式推导出它的导函数形式,弄懂bottom_data,top_data,bottom_diff,top_diff即可

Caffe 激励层(Activation)分析的更多相关文章

  1. caffe 每层结构

    如何在Caffe中配置每一个层的结构 最近刚在电脑上装好Caffe,由于神经网络中有不同的层结构,不同类型的层又有不同的参数,所有就根据Caffe官网的说明文档做了一个简单的总结. 1. Vision ...

  2. Android Hal层简要分析

    Android Hal层简要分析 Android Hal层(即 Hardware Abstraction Layer)是Google开发的Android系统里上层应用对底层硬件操作屏蔽的一个软件层次, ...

  3. ZT Android4.2关于bluetooth在HAL层的分析(1)

    我的电子杂烩饭 http://blog.sina.com.cn/wuchuchu2012 [订阅][手机订阅] 首页 博文目录 图片 关于我 正文 字体大小:大 中 小 Android4.2关于blu ...

  4. 1、Caffe数据层及参数

    要运行Caffe,需要先创建一个模型(model),每个模型由许多个层(layer)组成,每个层又都有自己的参数, 而网络模型和参数配置的文件分别是:caffe.prototxt,caffe.solv ...

  5. caffe︱ImageData层、DummyData层作为原始数据导入的应用

    Part1:caffe的ImageData层 ImageData是一个图像输入层,该层的好处是,直接输入原始图像信息就可以导入分析. 在案例中利用ImageData层进行数据转化,得到了一批数据. 但 ...

  6. 010商城项目:商品类目的选择——Dao,Service.Action层的分析

    我们现在开始写商品类选择这个功能: 先看效果: 当我们点击"新增商品"---->"选择目录"然后从数据库中查出来数据并显示了. 我们分析数据库的那张表: ...

  7. caffe特征层可视化

    #参考1:https://blog.csdn.net/sushiqian/article/details/78614133#参考2:https://blog.csdn.net/thy_2014/art ...

  8. 【转】caffe数据层及参数

    原文: 要运行caffe,需要先创建一个模型(model),如比较常用的Lenet,Alex等, 而一个模型由多个层(layer)构成,每一层又由许多参数组成.所有的参数都定义在caffe.proto ...

  9. [转] caffe视觉层Vision Layers 及参数

    视觉层包括Convolution, Pooling, Local Response Normalization (LRN), im2col等层. 1.Convolution层: 就是卷积层,是卷积神经 ...

随机推荐

  1. 洛谷P3358 最长k可重区间集问题(费用流)

    题目描述 对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度. 输入输出格式 输入格式: 的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区间的可重 ...

  2. D. Destruction of a Tree_dfs序_性质分析_思维题

    题意: 给定一棵树,每次可以拆掉一个树上度数为偶数的点,拆掉该点后,与该点所连的所有边都会被删掉.问,是否有一种删点顺序可以删掉所有的点.如果有,则输出任意一组解. 数据范围:线性做法 O(n)O(n ...

  3. IOS - No provisioning profiles with a valid signing identity 一种解决方法

    1.删除原有“钥匙串访问”中疑是过期的的证书: 2.在Member Center中Certificate中删除疑是有问题的Certificate,重新添加新的Certificate: 3.在“钥匙串访 ...

  4. NOI 2018 归程 (Kruskal重构树)

    题目大意:太长了,略 Kruskal重构树,很神奇的一个算法吧 如果两个并查集被某种条件合并,那么这个条件作为一个新的节点连接两个并查集 那么在接下来的提问中,如果某个点合法,它的所有子节点也都合法, ...

  5. Linux下安装Solr7.5.0,并部署到Tomcat

    收藏地址:https://blog.csdn.net/qq_39135287/article/details/84260724

  6. java实现随机数的生成

    一,课程中的动手动脑的问题 1,编写一个方法,使用以上算法生成指定数目的随机整数. public void suiJiShu(){ Scanner input=new Scanner(System.i ...

  7. 数人云CTO解读Docker 1.12和金融业容器化

    7月29日 数人云 在上海举办金融沙龙,邀请上交所和近二十家来自银行.保险.证券的IT技术专家一同探讨容器技术在金融业中的最佳实践.数人云CTO肖德时在会上将传统金融行业通过容器可以解决的四大问题做了 ...

  8. java深克隆与浅克隆

    2015.9.19 6:45   星期五    1

  9. C#-单元测试知识点

    指的是软件中对最小单元进行测试的一种测试方法 开发阶段的测试发现问题并解决问题是最节省时间和成本 Ctrl+R Ctrl+A 自动化执行单元测试 查看代码覆盖率,通常要达到80,90%的代码测试覆盖率 ...

  10. WinServer-IIS-IIS负载均衡

    安装应用程序路由 提供的服务器的地址必须是可以访问,不然无法进入到下面的这个管理界面 来自为知笔记(Wiz)