Caffe源码解析6:Neuron_Layer

2023-10-29 03:08
文章标签 源码 解析 caffe layer neuron

本文主要是介绍Caffe源码解析6:Neuron_Layer,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转自楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/

NeuronLayer,顾名思义这里就是神经元,激活函数的相应层。我们知道在blob进入激活函数之前和之后他的size是不会变的,而且激活值也就是输出 yy 只依赖于相应的输入 xx。在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)


如果有负斜率式子变为:

 

y=max(0,x)+νmin(0,x)y=max(0,x)+νmin(0,x)


反向传播的公式

 

∂E∂x=⎧⎩⎨ν∂E∂y∂E∂yifx≤0ifx>0∂E∂x={ν∂E∂yifx≤0∂E∂yifx>0


其在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))−1y=(1+exp⁡(−x))−1


其反向传播时

 

∂E∂x=∂E∂yy(1−y)∂E∂x=∂E∂yy(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。

ytrain={x1−p0if u>potherwiseytrain={x1−pif u>p0otherwise


其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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/297850

相关文章

nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析(结合应用场景)

《nginx-t、nginx-sstop和nginx-sreload命令的详细解析(结合应用场景)》本文解析Nginx的-t、-sstop、-sreload命令,分别用于配置语法检... 以下是关于 nginx -t、nginx -s stop 和 nginx -s reload 命令的详细解析,结合实际应

MyBatis中$与#的区别解析

《MyBatis中$与#的区别解析》文章浏览阅读314次,点赞4次,收藏6次。MyBatis使用#{}作为参数占位符时,会创建预处理语句(PreparedStatement),并将参数值作为预处理语句... 目录一、介绍二、sql注入风险实例一、介绍#(井号):MyBATis使用#{}作为参数占位符时,会

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

使用Python绘制3D堆叠条形图全解析

《使用Python绘制3D堆叠条形图全解析》在数据可视化的工具箱里,3D图表总能带来眼前一亮的效果,本文就来和大家聊聊如何使用Python实现绘制3D堆叠条形图,感兴趣的小伙伴可以了解下... 目录为什么选择 3D 堆叠条形图代码实现:从数据到 3D 世界的搭建核心代码逐行解析细节优化应用场景:3D 堆叠图

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决