1, src/caffe/proto/caffe.proto
在src/caffe/proto目录下有一个caffe.proto文件。
caffe.proto文件是一个消息格式文件,后缀名为proto.proto文件即消息协议原型定义文件,在该文件中可以通过使用描述性语言来定义程序中需要用到的数据格式。
proto文件是在Protobuf中定义使用的。Protobuf全称为GoogleProtocol Buffers,是Google的一个开源项目,它是一种结构化数据存储格式。
caffe.proto文件:
(1)、定义了很多结构化数据,用于构建Caffe网络,即*.prototxt文件中的每个字段名要在caffe.proto中存在;
(2)、负责*.caffemodel数据文件的存储和读取;
(3)、每次向Caffe中增加新的层,相应的caffe.proto文件也需调整,并需重新生成caffe.pb.h/caffe.pb.cc文件;
(4)、注意选择Protobuf的版本要与Caffe中的一致,否则会产生Protobuf版本不一致的error。
Google Protocol Buffer介绍
http://blog.csdn.net/yaonai2003/article/details/19573591
2, examples/mnist/lenet_train_val.protptxt
2.1 convolution_param
http://www.sohu.com/a/156004470_468740
下面看一下dilated conv原始论文[4]中的示意图:
(a)图对应3x3的1-dilated conv,和普通的卷积操作一样,
(b)图对应3x3的2-dilated conv,实际的卷积kernel size还是3x3,但是空洞为1,也就是对于一个7x7的图像patch,只有9个红色的点和3x3的kernel发生卷积操作,其余的点略过。也可以理解为kernel的size为7x7,但是只有图中的9个点的权重不为0,其余都为0。 可以看到虽然kernel size只有3x3,但是这个卷积的感受野已经增大到了7x7(如果考虑到这个2-dilated conv的前一层是一个1-dilated conv的话,那么每个红点就是1-dilated的卷积输出,所以感受野为3x3,所以1-dilated和2-dilated合起来就能达到7x7的conv),
(c)图是4-dilated conv操作,同理跟在两个1-dilated和2-dilated conv的后面,能达到15x15的感受野。对比传统的conv操作,3层3x3的卷积加起来,stride为1的话,只能达到(kernel-1)*layer+1=7的感受野,也就是和层数layer成线性关系,而dilated conv的感受野是指数级的增长。
dilated的好处是不做pooling损失信息的情况下,加大了感受野,让每个卷积输出都包含较大范围的信息。在图像需要全局信息或者语音文本需要较长的sequence信息依赖的问题中,都能很好的应用dilated conv,比如图像分割[3]、语音合成WaveNet[2]、机器翻译ByteNet[1]中。简单贴下ByteNet和WaveNet用到的dilated conv结构,可以更形象的了解dilated conv本身。
ByteNet
WaveNet
下面再阐述下deconv和dilated conv的区别:
deconv的具体解释可参见如何理解深度学习中的deconvolution networks?,deconv的其中一个用途是做upsampling,即增大图像尺寸。而dilated conv并不是做upsampling,而是增大感受野。可以形象的做个解释:
2.2 inner_product_param
2.3 ReLU layer
layer{
type:"ReLU"
}
http://blog.csdn.net/m0_37407756/article/details/72553284
caffe中weight_filler
文件filler.hpp提供了7种权值初始化的方法,分别为:常量初始化(constant)、高斯分布初始化(gaussian)、positive_unitball初始化、均匀分布初始化(uniform)、xavier初始化、msra初始化、双线性初始化(bilinear)。
Filter类在Caffe中用来初始化权值大小,有如下表的类型:
类型 | 派生类 | 说明 |
---|---|---|
constant | ConstantFiller | 使用一个常数(默认为0)初始化权值 |
gaussian | GaussianFiller | 使用高斯分布初始化权值 |
positive_unitball | PositiveUnitballFiller |
|
uniform | UniformFiller | 使用均为分布初始化权值 |
xavier | XavierFiller | 使用xavier算法初始化权值 |
msra | MSRAFiller |
|
bilinear | BilinearFiller |
|
constant初始化方法:
它就是把权值或着偏置初始化为一个常数,具体是什么常数,自己可以定义啦。它的值等于.prototxt文件中的value的值,默认为0
下面是是与之相关的.proto文件里的定义,在定义网络时,可能分用到这些参数。
optional string type = 1 [default =
'constant'];
optional float
value = http://www.cnblogs.com/yinheyi/p/2 [default = 0]; // the
value in constant filler
uniform初始化方法
它的作用就是把权值与偏置进行 均匀分布的初始化。用min与max来控制它们的的上下限,默认为(0,1).
下面是是与之相关的.proto文件里的定义,在定义网络时,可能分用到这些参数。
45 optional string type = 1 [default =
'constant'];
47 optional float min = 3 [default = 0]; //
the min value in uniform filler
48 optional
float max = 4 [default = 1]; // the max value in uniform filler
Gaussian初始化
给定高斯函数的均值与标准差,生成高斯分布就可以了。
不过要说明一点的就是,gaussina初始化可以进行sparse,意思就是可以把一些权值设为0.控制它的用参数sparse.sparse表示相对于num_output来说非0的个数,在代码实现中,会把sparse/num_output作为bernoulli分布的概率,生成的bernoulli分布的数字(为0或1)与原来的权值相乘,就可以实现一部分权值为0了。
下面是是与之相关的.proto文件里的定义,在定义网络时,可能分用到这些参数。
45 optional string type = 1 [default =
'constant'];
49 optional float mean = 5 [default = 0]; //
the mean value in Gaussian filler
50 optional float std = 6 [default = 1]; //
the std value in Gaussian filler
51 // The expected number of non-zero output
weights for a given input in
52 // Gaussian filler -- the default -1
means don't perform sparsification.
53 optional
int32 sparse = 7 [default = -1];
positive_unitball初始化
通俗一点,它干了点什么呢?即让每一个单元的输入的权值的和为1. 例如吧,一个神经元有100个输入,这样的话,让这100个输入的权值的和为1.源码中怎么实现的呢?首先给这100个权值赋值为在(0,1)之间的均匀分布,然后,每一个权值再除以它们的和就可以啦。
感觉这么做,可以有助于防止权值初始化过大,使激活函数(sigmoid函数)进入饱和区。所以呢,它应该比适合simgmoid形的激活函数。
它不需要参数去控制。
XavierFiller初始化:
对于这个初始化的方法,是有理论的。它来自这篇论文《Understandingthe difficulty of training deep feedforward neuralnetworks》。在推导过程中,我们认为处于tanh激活函数的线性区,所以呢,对于ReLU激活函数来说,XavierFiller初始化也是很适合啦。
如果不想看论文的话,可以看看 https://zhuanlan.zhihu.com/p/22028079,我觉得写的很棒,另外,http://blog.csdn.net/shuzfan/article/details/51338178可以作为补充。
它的思想就是让一个神经元的输入权重的(当反向传播时,就变为输出了)的方差等于:1/ 输入的个数;这样做的目的就是可以让信息可以在网络中均匀的分布一下。
对于权值的分布:是一个让均值为0,方差为1/ 输入的个数的 均匀分布。
如果我们更注重前向传播的话,我们可以选择fan_in,即正向传播的输入个数;如果更注重后向传播的话,我们选择fan_out,因为,等着反向传播的时候,fan_out就是神经元的输入个数;如果两者都考虑的话,那就选 average= (fan_in + fan_out) /2
下面是是与之相关的.proto文件里的定义,在定义网络时,可能分用到这些参数。
<span style="color:#000000">45 optional string type
= 1 [default = 'constant'];</span>
<span style="color:#000000"> 54 // Normalize the
filler variance by fan_in, fan_out, or their average.</span>
55 //www.90168.org
Applies to 'xavier' and 'msra' fillers.
www.90168.org
Applies to 'xavier' and 'msra' fillers.
<span style="color:#000000"> 56 enum VarianceNorm {</span>
<span style="color:#000000"> 57 FAN_IN = 0;</span>
<span style="color:#000000"> 58 FAN_OUT = 1;
</span>
<span style="color:#000000"> 59 AVERAGE = 2;</span>
<span style="color:#000000"> 60 }</span>
<span style="color:#000000">
61 optional VarianceNorm variance_norm = 8 [default = FAN_IN];</span>
MSRAFiller初始化方式
它与上面基本类似,它是基于《DelvingDeep into Rectifiers:Surpassing Human-Level Performance on ImageNetClassification》来推导的,并且呢,它是基于激活函数为ReLU函数哦,
对于权值的分布,是基于均值为0,方差为2/输入的个数的高斯分布,这也是和上面的XavierFiller不同的地方;它特别适合激活函数为ReLU函数的啦。
下面是是与之相关的.proto文件里的定义,在定义网络时,可能分用到这些参数。
45 optional string type = 1 [default =
'constant'];
54 // Normalize the filler variance by
fan_in, fan_out, or their average.
55 // Applies to 'xavier' and 'msra'
fillers.
56 enum VarianceNorm {
57 FAN_IN = 0;
58 FAN_OUT = 1;
59 AVERAGE = 2;
60 }
61 optional
VarianceNorm variance_norm = 8 [default = FAN_IN];
BilinearFiller初始化
对于它,要还没有怎么用到过,它常用在反卷积神经网络里的权值初始化;
直接上源码,大家看看吧;
3,include/caffe/layer/neural_layers.hpp
4, src/caffe/layers/relu_layer.cpp