caffe权值初始化方式
在caffe/include/caffe/目录下有一个滤波器的权值类头文件,即filler.hpp文件。该Filler类的作用实际上就是根据prototxt文件中的weight_filler参数如下所示:
既然是权值要初始化,除了调用预训练模型的参数外,初始化的方式总共有几种呢,在filler.hpp文件中定义了7种初始化方式:分别为常量初始化(constant)、高斯分布初始化(gaussian)、positive_unitball初始化、均匀分布初始化(uniform)、xavier初始化、msra初始化、双线性初始化(bilinear)
源码在filler.hpp文件中,如下:
template <typename Dtype>
Filler<Dtype>* GetFiller(const FillerParameter& param) {
const std::string& type = param.type();
if (type == "constant") {
return new ConstantFiller<Dtype>(param);
} else if (type == "gaussian") {
return new GaussianFiller<Dtype>(param);
} else if (type == "positive_unitball") {
return new PositiveUnitballFiller<Dtype>(param);
} else if (type == "uniform") {
return new UniformFiller<Dtype>(param);
} else if (type == "xavier") {
return new XavierFiller<Dtype>(param);
} else if (type == "msra") {
return new MSRAFiller<Dtype>(param);
} else if (type == "bilinear") {
return new BilinearFiller<Dtype>(param);
} else {
CHECK(false) << "Unknown filler name: " << param.type();
}
return (Filler<Dtype>*)(NULL);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
下边一种种来了解:
第一种:constant常量初始化。
它就是把权值或着偏置初始化为一个常数,具体是什么常数,自己可以定义啦。它的值等于.prototxt文件中的 value 的值,默认为0
第二种:uniform均匀分布初始化。
它的作用就是把权值与偏置进行均匀分布的初始化。用min 与 max 来控制它们的的上下限,默认为(0,1).f(x)={1b−aa<x<b0else” role=”presentation”>f(x)={1b−a0a<x<belsef(x)={1b−aa<x<b0else
第三种:Gaussian初始化。
给定高斯函数的均值与标准差,生成高斯分布就可以了。
不过要说明一点的就是, gaussina初始化可以进行 sparse,意思就是可以把一些权值设为0. 控制它的用参数 sparse. sparse表示相对于 num_output来说非0的个数,在代码实现中,会把 sparse/num_output 作为 bernoulli分布的概率, 生成的bernoulli分布的数字(为0或1)与原来的权值相乘,就可以实现一部分权值为0了。
高斯分布公式:f(x;μ,σ)=12πσexp(−(x−μ)22σ2)” role=”presentation”>f(x;μ,σ)=12π√σexp(−(x−μ)22σ2)f(x;μ,σ)=12πσexp(−(x−μ)22σ2)
第四种:positive_unitball初始化。
通俗一点,它干了点什么呢?即让每一个单元的输入的权值的和为 1. 例如吧,一个神经元有100个输入,这样的话,让这100个输入的权值的和为1. 源码中怎么实现的呢? 首先给这100个权值赋值为在(0,1)之间的均匀分布,然后,每一个权值再除以它们的和就可以啦。
感觉这么做,可以有助于防止权值初始化过大,使激活函数(sigmoid函数)进入饱和区。所以呢,它应该比适合simgmoid形的激活函数。
它不需要参数去 控制。
第五种:XavierFiller初始化。
(这里参考了博客:https://blog.csdn.net/shuzfan/article/details/51338178)
对于权值的分布:是一个让均值为0,方差为1 / 输入的个数 的 均匀分布。
深度网络学习的实际上是学习特征的分布,那么我们希望数据在传输的过程中,分布要改变,也就是说,数据输入和输出的方差不要改变最好。
输出: 其中ni” role=”presentation”>nini表示输入的个数
输出的方差为:
要想使输入和输出(方差)分布一致,则niVar(wi)” role=”presentation”>niVar(wi)niVar(wi) = 1。
则有:Var(wi)=1ni” role=”presentation”>Var(wi)=1niVar(wi)=1ni
为了保证前向和反向传播时每一层的方差一致,应满足:
其中ni” role=”presentation”>nini分别为输入个数和输出个数
有:∀i,Var[wi]=2ni+ni+1” role=”presentation”>∀i,Var[wi]=2ni+ni+1∀i,Var[wi]=2ni+ni+1
学过概率统计的都知道 [a,b] 间的均匀分布的方差为:
Var=(b−a)212” role=”presentation”>Var=(b−a)212Var=(b−a)212
因此:Xavier初始化的实现就是下面的均匀分布:
第六种:MSRAFiller初始化方式。
对于权值的分布:是基于均值为0,方差为 2 /输入的个数 的高斯分布。这也是和上面的Xavier Filler不同的地方;它特别适合激活函数为 ReLU函数的啦。可以参考博客:
第七种:BilinearFiller初始化。
常用于语义分割实例分割等网络中的反卷积的权值初始化。
在caffe/include/caffe/目录下有一个滤波器的权值类头文件,即filler.hpp文件。该Filler类的作用实际上就是根据prototxt文件中的weight_filler参数如下所示:
既然是权值要初始化,除了调用预训练模型的参数外,初始化的方式总共有几种呢,在filler.hpp文件中定义了7种初始化方式:分别为常量初始化(constant)、高斯分布初始化(gaussian)、positive_unitball初始化、均匀分布初始化(uniform)、xavier初始化、msra初始化、双线性初始化(bilinear)
源码在filler.hpp文件中,如下:
template <typename Dtype>
Filler<Dtype>* GetFiller(const FillerParameter& param) {
const std::string& type = param.type();
if (type == "constant") {
return new ConstantFiller<Dtype>(param);
} else if (type == "gaussian") {
return new GaussianFiller<Dtype>(param);
} else if (type == "positive_unitball") {
return new PositiveUnitballFiller<Dtype>(param);
} else if (type == "uniform") {
return new UniformFiller<Dtype>(param);
} else if (type == "xavier") {
return new XavierFiller<Dtype>(param);
} else if (type == "msra") {
return new MSRAFiller<Dtype>(param);
} else if (type == "bilinear") {
return new BilinearFiller<Dtype>(param);
} else {
CHECK(false) << "Unknown filler name: " << param.type();
}
return (Filler<Dtype>*)(NULL);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
下边一种种来了解:
第一种:constant常量初始化。
它就是把权值或着偏置初始化为一个常数,具体是什么常数,自己可以定义啦。它的值等于.prototxt文件中的 value 的值,默认为0
第二种:uniform均匀分布初始化。
它的作用就是把权值与偏置进行均匀分布的初始化。用min 与 max 来控制它们的的上下限,默认为(0,1).f(x)={1b−aa<x<b0else” role=”presentation”>f(x)={1b−a0a<x<belsef(x)={1b−aa<x<b0else
第三种:Gaussian初始化。
给定高斯函数的均值与标准差,生成高斯分布就可以了。
不过要说明一点的就是, gaussina初始化可以进行 sparse,意思就是可以把一些权值设为0. 控制它的用参数 sparse. sparse表示相对于 num_output来说非0的个数,在代码实现中,会把 sparse/num_output 作为 bernoulli分布的概率, 生成的bernoulli分布的数字(为0或1)与原来的权值相乘,就可以实现一部分权值为0了。
高斯分布公式:f(x;μ,σ)=12πσexp(−(x−μ)22σ2)” role=”presentation”>f(x;μ,σ)=12π√σexp(−(x−μ)22σ2)f(x;μ,σ)=12πσexp(−(x−μ)22σ2)
第四种:positive_unitball初始化。
通俗一点,它干了点什么呢?即让每一个单元的输入的权值的和为 1. 例如吧,一个神经元有100个输入,这样的话,让这100个输入的权值的和为1. 源码中怎么实现的呢? 首先给这100个权值赋值为在(0,1)之间的均匀分布,然后,每一个权值再除以它们的和就可以啦。
感觉这么做,可以有助于防止权值初始化过大,使激活函数(sigmoid函数)进入饱和区。所以呢,它应该比适合simgmoid形的激活函数。
它不需要参数去 控制。
第五种:XavierFiller初始化。
(这里参考了博客:https://blog.csdn.net/shuzfan/article/details/51338178)
对于权值的分布:是一个让均值为0,方差为1 / 输入的个数 的 均匀分布。
深度网络学习的实际上是学习特征的分布,那么我们希望数据在传输的过程中,分布要改变,也就是说,数据输入和输出的方差不要改变最好。
输出: 其中ni” role=”presentation”>nini表示输入的个数
输出的方差为:
要想使输入和输出(方差)分布一致,则niVar(wi)” role=”presentation”>niVar(wi)niVar(wi) = 1。
则有:Var(wi)=1ni” role=”presentation”>Var(wi)=1niVar(wi)=1ni
为了保证前向和反向传播时每一层的方差一致,应满足:
其中ni” role=”presentation”>nini分别为输入个数和输出个数
有:∀i,Var[wi]=2ni+ni+1” role=”presentation”>∀i,Var[wi]=2ni+ni+1∀i,Var[wi]=2ni+ni+1
学过概率统计的都知道 [a,b] 间的均匀分布的方差为:
Var=(b−a)212” role=”presentation”>Var=(b−a)212Var=(b−a)212
因此:Xavier初始化的实现就是下面的均匀分布:
第六种:MSRAFiller初始化方式。
对于权值的分布:是基于均值为0,方差为 2 /输入的个数 的高斯分布。这也是和上面的Xavier Filler不同的地方;它特别适合激活函数为 ReLU函数的啦。可以参考博客:
第七种:BilinearFiller初始化。
常用于语义分割实例分割等网络中的反卷积的权值初始化。