零基础学caffe源码 ReLU激活函数

原创 2016年08月03日 17:30:19

1、如何有效阅读caffe源码

1、caffe源码阅读路线最好是从src/cafffe/proto/caffe.proto开始,了解基本数据结构内存对象和磁盘文件的一一映射关系,中间过程都由ProtoBuffer工具自动完成。

2、看include/目录中.hpp头文件,通过头文件类申明理解整个框架。从基类向派生类,掌握这些类。

3、看src/目录中.cpp和.cu源文件,亦可以按需求派生新的类。

4、编写各类工具,集成到caffe内部,如tools/下就有训练模型,提取特征,转换数据格式等工具。

2、ReLU激活函数

激活函数,用在各个卷积层和全连接层输出位置。激活函数是深度网络非线性的主要来源。通常包括:simgoid(f(x)=(1+e-x)-1)和tanh(f(x)=sinhx/coshx,图形类似于arctanx,但是值域是[-1,1])作为激活函数。

用ReLU(f(x)=max(0,x))作为激活函数的原因是:加速收敛、解决了梯度消失问题

3、ReLU函数caffe源码解析

在models/bvlc_alexnet/train_val.prototxt网络模型设置中找到了ReLU层描述

[cpp] view plain copy
  1. //ReLU层,新的非线性层
  2. layer {
  3. name: "relu1"  //层名
  4. type: "ReLU"  //层类型
  5. bottom: "conv1"  //层输入
  6. top: "conv1"  //层输出
  7. }

下面开始按步骤解析源码:
3.1、阅读src/cafffe/proto/caffe.proto中ReLU层参数

[cpp] view plain copy
  1. //存储ReLU层参数的数据结构类
  2. message ReLUParameter {
  3. //message:数据结构类,ReLUParameter为其对象
  4. //optional;表示一个可选字段,required:表示一个必须字段
  5. //repeated:表示该字段可以包含多个元素,和optional特性相同,类似数组
  6. optional float negative_slope = 1 [default = 0];
  7. enum Engine {  //枚举Engine中所有元素
  8. DEFAULT = 0;
  9. CAFFE = 1;
  10. CUDNN = 2;
  11. }
  12. optional Engine engine = 2 [default = DEFAULT];
  13. }

3.2、阅读include/caffe/layers/relu_layer.hpp中类申明

[cpp] view plain copy
  1. <span style="font-family:KaiTi_GB2312;font-size:24px;">//头文件中的 #ifndef/#define/#endif,防止该头文件被重复引用
  2. #ifndef CAFFE_RELU_LAYER_HPP_
  3. #define CAFFE_RELU_LAYER_HPP_
  4. #include <vector>
  5. #include "caffe/blob.hpp"
  6. #include "caffe/layer.hpp"
  7. #include "caffe/proto/caffe.pb.h"
  8. #include "caffe/layers/neuron_layer.hpp"
  9. //ReLULayer,派生于NeuronLayer,实现了ReLU激活函数计算
  10. namespace caffe {
  11. //template:指定模板类型参数,Dtype:表示一个类型
  12. template <typename Dtype>
  13. //新定义ReLULayer类,其继承NeuronLayer类
  14. class ReLULayer : public NeuronLayer<Dtype> {
  15. public:
  16. //显式构造函数,NeuronLayer的参数显式传递给ReLULayer,LayerParameter:protobuf文件中存储的layer参数
  17. explicit ReLULayer(const LayerParameter& param)
  18. : NeuronLayer<Dtype>(param) {}
  19. //虚内联函数,const成员函数,返回类名字符串
  20. virtual inline const char* type() const { return "ReLU"; }
  21. protected:  //bottom为输入,top为输出
  22. //前向传播函数
  23. //CPU版本前馈实现
  24. virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
  25. const vector<Blob<Dtype>*>& top);
  26. //GPU版本前馈实现
  27. virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
  28. const vector<Blob<Dtype>*>& top);
  29. //反向传播函数
  30. //top为输出blob,propagate_down为bottom索引,bottom为输入blob
  31. virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
  32. const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
  33. virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
  34. const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
  35. };
  36. }  // namespace caffe
  37. #endif  // CAFFE_RELU_LAYER_HPP_</span>

3.3、阅读src/caffe/layers/relu_layer.cpp中代码

[cpp] view plain copy
  1. <span style="font-family:KaiTi_GB2312;font-size:24px;">#include <algorithm>
  2. #include <vector>
  3. #include "caffe/layers/relu_layer.hpp"
  4. namespace caffe {
  5. template <typename Dtype>
  6. //定义前向传播函数
  7. void ReLULayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
  8. const vector<Blob<Dtype>*>& top) {
  9. //(只读)获得输入blob的data指针
  10. const Dtype* bottom_data = bottom[0]->cpu_data(); //->:指针引用
  11. //(读写)获得输出blob的data指针
  12. Dtype* top_data = top[0]->mutable_cpu_data();
  13. //获得输入blob元素个数
  14. const int count = bottom[0]->count();
  15. //Leak ReLU参数,从layer_param_中获得,默认为0(negative_slope=0),即普通ReLU
  16. Dtype negative_slope = this->layer_param_.relu_param().negative_slope();
  17. for (int i = 0; i < count; ++i) {
  18. top_data[i] = std::max(bottom_data[i], Dtype(0)) //ReLU(f(x)=max(0,x))
  19. + negative_slope * std::min(bottom_data[i], Dtype(0));
  20. }
  21. }
  22. template <typename Dtype>
  23. //定义反向传播函数
  24. void ReLULayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
  25. const vector<bool>& propagate_down,
  26. const vector<Blob<Dtype>*>& bottom) {
  27. //如果需要做反向传播计算,propagate_down是与计算关于bottom的梯度相关,
  28. //在caffe的BP实现中非常重要
  29. if (propagate_down[0]) {
  30. //(只读)获得前一层的data指针,data:前向传播所用数据
  31. const Dtype* bottom_data = bottom[0]->cpu_data();
  32. //(只读)获得后一层的diff指针,diff:反向传播所用数据
  33. const Dtype* top_diff = top[0]->cpu_diff();
  34. //(读写)获得前一层的diff指针,是损失函数关于当前层的输入(bottom)的偏导数
  35. Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
  36. //获得需要参与计算的元素总和
  37. const int count = bottom[0]->count();
  38. //Leaky ReLU参数,默认为0
  39. Dtype negative_slope = this->layer_param_.relu_param().negative_slope();
  40. for (int i = 0; i < count; ++i) {
  41. //ReLU的导函数就是(bottom_data[i] > 0,根据求导链式法则,后一层的误差乘以导函数得到前一层的误差
  42. bottom_diff[i] = top_diff[i] * ((bottom_data[i] > 0)
  43. + negative_slope * (bottom_data[i] <= 0));  //negative_slope=0
  44. }
  45. }
  46. }
  47. #ifdef CPU_ONLY
  48. STUB_GPU(ReLULayer);
  49. #endif
  50. INSTANTIATE_CLASS(ReLULayer);
  51. }  // namespace caffe</span>

零基础学caffe源码 ReLU激活函数相关推荐

  1. 零基础入门Cobra---kubernetes源码学习必备

    Cobra 是用 go 语言实现的用于创建 CLI 应用程序和命令文件的工具. 许多 Go 的项目都是使用 Cobra 构建的,包括: kubernetes etcd hugo docker -- 本 ...

  2. caffe源码分析-layer

    本文主要分析caffe layer层,主要内容如下: 从整体上说明下caffe的layer层的类别,以及作用 通过proto定义与类Layer简要说明下Layer的核心成员变量; Layer类的核心成 ...

  3. java int类源码,一起学JDK源码 -- Integer类

    Integer类为java基本类型int的包装类,除了前面提到的Byte类,Short类中的大部分方法,Integer类中还提供了很多处理int类型的方法,接下来就让我们一起看看吧. 基础知识: 1. ...

  4. python零基础看什么视频和书籍-资料│最适合大学生零基础学的Python视频+电子书...

    原标题:资料│最适合大学生零基础学的Python视频+电子书 月最热资源下载 (▲点击阅读) 已经不少童鞋跟播妞咨询了python的资源 今天播妞将整理好的部分python资源发布 是最适合零基础大学 ...

  5. python零基础电子书免费下载-零基础学Python

    准备自学Python朋友,不放来看看<零基础学Python>吧!小编这里为各位送上的是这本书的全彩PDF版,该书从初学者角度出发,通过通俗易懂的语言.流行有趣的实例,详细地介绍了使用IDL ...

  6. 编程没基础学python多长时间--零基础学Python,从入门到精通需要多长时间

    求一份小甲鱼的<零基础入门学习Python>视频教程 评论 本系列教程面向础的同学,是一个深入浅通俗易懂的Python3视频教程. 适群 完全零基础入门,不需要任何前置知识. 教程概述 前 ...

  7. 零基础学python全彩版实战答案-零基础学Python(全彩版)

    商品描述: 本店出售的图书均是正版二手书,有一些笔记划线,基本是六-九品新左右,基本都没有光盘.介意者请提前咨询客服.本店所有书籍,因买家导致退货退款的,发出运费参照不包邮运费模板由买家承担.如果签收 ...

  8. Deep Compression阅读理解及Caffe源码修改

    Deep Compression阅读理解及Caffe源码修改 作者:may0324 更新:  没想到这篇文章写出后有这么多人关注和索要源码,有点受宠若惊.说来惭愧,这个工作当时做的很粗糙,源码修改的比 ...

  9. 零基础学Java的10个方法

    2019独角兽企业重金招聘Python工程师标准>>> 版权声明:本文为北京尚学堂原创文章,未经允许不得转载.​ 零基础学Java只要方法得当,依然有机会学习好Java编程. 但作为 ...

最新文章

  1. 原理解释|直觉与实现:Batch Normalization
  2. reverse mapping checking getaddrinfo for bogon failed – POSSIBLE BREAK-IN ATTEMPT! 错误
  3. 原来带有python又装了一个anaconda有影响吗_anaconda python环境与原有python环境的坑...
  4. GDCM:获取图像像素间距的测试程序
  5. .NET2.0学习资料
  6. mysql获取多张表中的数据_mysql 之多表查询
  7. 用NSoup解析HTML
  8. [css] 写出你遇到过IE6/7/8/9的BUG及解决方法
  9. java策略_java策略模式
  10. Spring Cloud Eureka 最简入门示例
  11. 知识图谱组队学习Task04——知识库的查询语句
  12. 软件测试与软件开发比较?
  13. 实操:(附环摄数据及三维模型)如何利用Smart3D将二维照片转换成三维模型?
  14. LEADBBS 不要验证码
  15. 设计模式之策略模式:模拟鸭子
  16. 使用Excel 2007绘制甘特图
  17. AppStore上线审核
  18. LINUX TC介绍
  19. 最大字数组求和改进!
  20. 微信小程序 富文本组件使用

热门文章

  1. java解锁_Java 姿势解锁 —— Lists.transform
  2. mysql 织梦 索引_Mysql索引详解 建立索引的优势劣势以及索引规范
  3. linux系统不关机添加硬盘吗,CentOS中不重启添加硬盘
  4. jsp 跳到servlet路径_直接访问Jsp和从Servlet跳转到Jsp时的路径问题
  5. oracle部署在mysql_Oracle数据库部署实施流程
  6. php怎么添加框架,PHPWind 给默认的风格添加大框架
  7. linux里打包和压缩文件,linux ---打包和压缩文件
  8. 不可思议!乌克兰国防军队的系统账密居然是 admin 和 123456...
  9. 你觉得 ThreadLocalRandom 这玩意真的安全吗?
  10. 如何在代码中获取Java应用当前的版本号?