转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/

NeuronLayer,顾名思义这里就是神经元,激活函数的相应层。我们知道在blob进入激活函数之前和之后他的size是不会变的,而且激活值也就是输出 \(y\) 只依赖于相应的输入 \(x\)。在Caffe里面所有的layer的实现都放在src文件夹下的layer文件夹中,基本上很多文章里应用到的layer类型它都有cpu和cuda的实现。

在caffe里面NeuronLayer比较多,在此罗列了一下

  • AbsValLayer
  • BNLLLayer
  • DropoutLayer
  • ExpLayer
  • LogLayer
  • PowerLayer
  • ReLULayer
  • CuDNNReLULayer
  • SigmoidLayer
  • CuDNNSigmoidLayer
  • TanHLayer
  • CuDNNTanHLayer
  • ThresholdLayer
  • PReLULayer

Caffe里面的Neuron种类比较多方便人们使用,这里我们着重关注几个主要的Neuro_layer

ReLULayer

目前在激活层的函数中使用ReLU是非常普遍的,一般我们在看资料或者讲义中总是提到的是Sigmoid函数,它比Sigmoid有更快的收敛性,因为sigmoid在收敛的时候越靠近目标点收敛的速度会越慢,也是其函数的曲线形状决定的。而ReLULayer则相对收敛更快,具体可以看Krizhevsky 12年的那篇ImageNet CNN文章有更详细的介绍。

其计算的公式是:

\[y = \max(0, x)
\]

如果有负斜率式子变为:

\[y = \max(0, x) + \nu \min(0, x)
\]

反向传播的公式

\[ \frac{\partial E}{\partial x} = \left\{
\begin{array}{lr}
\nu \frac{\partial E}{\partial y} & \mathrm{if} \; x \le 0 \\
\frac{\partial E}{\partial y} & \mathrm{if} \; x > 0
\end{array} \right.
\]

其在cafffe中的forward和backward函数为

template <typename Dtype>
void ReLULayer<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();
const int count = bottom[0]->count();
Dtype negative_slope = this->layer_param_.relu_param().negative_slope();
for (int i = 0; i < count; ++i) {
top_data[i] = std::max(bottom_data[i], Dtype(0))
+ negative_slope * std::min(bottom_data[i], Dtype(0));
}
} template <typename Dtype>
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));
}
}
}

SigmoidLayer

Sigmoid函数,也称为阶跃函数,函数曲线是一个优美的S形。目前使用Sigmoid函数已经不多了,大多使用ReLU来代替,其对应的激活函数为:

\[y = (1 + \exp(-x))^{-1}
\]

其反向传播时

\[\frac{\partial E}{\partial x}
= \frac{\partial E}{\partial y} y (1 - y)\]

其相应的forward和backward的函数为

template <typename Dtype>
void SigmoidLayer<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();
const int count = bottom[0]->count();
for (int i = 0; i < count; ++i) {
top_data[i] = sigmoid(bottom_data[i]);
}
} template <typename Dtype>
void SigmoidLayer<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_data = top[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();
for (int i = 0; i < count; ++i) {
const Dtype sigmoid_x = top_data[i];
bottom_diff[i] = top_diff[i] * sigmoid_x * (1. - sigmoid_x);
}
}
}

DropoutLayer

DropoutLayer现在是非常常用的一种网络层,只用在训练阶段,一般用在网络的全连接层中,可以减少网络的过拟合问题。其思想是在训练过程中随机的将一部分输入x之置为0。

\[y_{\mbox{train}} = \left\{
\begin{array}{ll}
\frac{x}{1 - p} & \mbox{if } u > p \\
0 & \mbox{otherwise}
\end{array} \right.
\]

其forward_cpu和backward_cpu为:

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构造随机数,这里是通过向量掩码来和bottom的数据相乘,scale_是控制undropped的比例
caffe_rng_bernoulli(count, 1. - threshold_, mask);
for (int i = 0; i < count; ++i) {
top_data[i] = bottom_data[i] * mask[i] * scale_;
}
} else {
caffe_copy(bottom[0]->count(), bottom_data, 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();
for (int i = 0; i < count; ++i) {
bottom_diff[i] = top_diff[i] * mask[i] * scale_;
}
} else {
caffe_copy(top[0]->count(), top_diff, bottom_diff);
}
}
}

Caffe源码解析6:Neuron_Layer的更多相关文章

  1. Caffe源码解析7:Pooling_Layer

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ Pooling 层一般在网络中是跟在Conv卷积层之后,做采样 ...

  2. Caffe源码解析5:Conv_Layer

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ Vision_layer里面主要是包括了一些关于一些视觉上的操 ...

  3. Caffe源码解析4: Data_layer

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ data_layer应该是网络的最底层,主要是将数据送给blo ...

  4. Caffe源码解析3:Layer

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ layer这个类可以说是里面最终的一个基本类了,深度网络呢就是 ...

  5. Caffe源码解析2:SycedMem

    转载请注明出处,楼燚(yì)航的blog,http://www.cnblogs.com/louyihang loves baiyan/ 看到SyncedMem就知道,这是在做内存同步的操作.这类个类的 ...

  6. Caffe源码解析1:Blob

    转载请注明出处,楼燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/ 首先看到的是Blob这个类,Blob是作为Caffe中数据流通的 ...

  7. caffe源码解析

    http://blog.csdn.net/lanxuecc/article/details/53186613

  8. caffe源码阅读

    参考网址:https://www.cnblogs.com/louyihang-loves-baiyan/p/5149628.html 1.caffe代码层次熟悉blob,layer,net,solve ...

  9. 【Caffe】源码解析----caffe.proto (转载)

    分析caffe源码,看首先看caffe.proto,是明智的选择.好吧,我不是创造者,只是搬运工. 原文地址:http://blog.csdn.net/qq_16055159/article/deta ...

随机推荐

  1. javascript超过容器后显示省略号效果(兼容一行或者多行)

    javascript超过容器后显示省略号效果       在实际的项目中,由于文字内容的长度不确定性和页面布局的固定性,难免会出现文字内容超过div(或其他标签,下同)区域的情况,此时比较好的做法就是 ...

  2. .Net(c#)模拟Http请求之HttpWebRequest封装

    一.需求: 向某个服务发起请求获取数据,如:爬虫,采集. 二.步骤(HttpWebRequest): 无非在客户端Client(即程序)设置请求报文(如:Method,Content-Type,Age ...

  3. SSH(Struts2+Spring+Hibernate)框架搭建流程<注解的方式创建Bean>

    此篇讲的是MyEclipse9工具提供的支持搭建自加包有代码也是相同:用户登录与注册的例子,表字段只有name,password. SSH,xml方式搭建文章链接地址:http://www.cnblo ...

  4. Lind.DDD.IoC(大叔推荐)~在服务定位器中引入IoC容器~容器的适配器

    回到目录 关于依赖倒置(DIP) 高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口,通俗的讲,就是高层模块定义接口,低层模块负责实现,这在我们实际开发中经常被用到,层与层之间引用,经 ...

  5. C#中JSON序列化和反序列化

    有一段时间没有到博客园写技术博客了,不过每天逛逛博客园中大牛的博客还是有的,学无止境…… 最近在写些调用他人接口的程序,用到了大量的JSON.XML序列化和反序列化,今天就来总结下json的序列化和反 ...

  6. css制作漂亮彩带导航条菜单

    点击这里查看效果:http://keleyi.com/keleyi/phtml/divcss/17.htm 效果图: 以下是源代码: <!DOCTYPE html PUBLIC "-/ ...

  7. angular源码分析:angular中入境检察官$sce

    一.ng-bing-html指令问题 需求:我需要将一个变量$scope.x = '<a href="http://www.cnblogs.com/web2-developer/&qu ...

  8. 轻松掌握:JavaScript单例模式

    单例模式 定义:保证一个对象(类)仅有一个实例,并提供一个访问它的全局访问点: 实现原理:利用闭包来保持对一个局部变量的引用,这个变量保存着首次创建的唯一的实例; 主要用于:全局缓存.登录浮窗等只需要 ...

  9. javascript的函数(二)

    1. 函数的作用域 作用域是指变量的存在的范围.javascript中有两种作用域,一种是全局作用域,变量在整个程序中一直存在,另一种是函数作用域,变量只存在于函数体内部.在函数体外部声明的变量就是全 ...

  10. Android开发6:Service的使用(简单音乐播放器的实现)

    前言 啦啦啦~各位好久不见啦~博主最近比较忙,而且最近一次实验也是刚刚结束~ 好了不废话了,直接进入我们这次的内容~ 在这篇博文里我们将学习Service(服务)的相关知识,学会使用 Service ...