对于一个神经元来说,需要初始化的参数有两类:一类是权重W,还有一类是偏置b,虽然偏置b的初始化为可以使用0或者随机书代替,但是权重的初始化会对模型的训练有重要影响。
权重的初始化最好不要用零或随机数初始化权重,因为如果初始权重太小,则信号在穿过每一层时会收缩,会导致小而无用。如果初始权重太大,则信号在穿过每一层时会不断增长,直到其太大而无法使用为止。
因此我们的原则是:
- 不建议同时初始化为一个值,容易出现“对称失效”;
- 最好保证均值为0,正负交错,参数大致数量相等;
- 初始化参数不要太大或太小,前者会导致梯度发散难以训练,后者会导致特征对后面的影响逐渐变小。
tensorflow 权重初始化方法
这是tensorflow 2中的初始化权重的方法,不同维度的卷积设置不同,如下: 1维卷积Conv1D及其反卷积Conv1DTranspose:
tf.keras.layers.Conv1D(
filters,
kernel_size,
strides=1,
padding='valid',
data_format='channels_last',
dilation_rate=1,
groups=1,
activation=None,
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
**kwargs
)
tf.keras.layers.Conv1DTranspose(
filters,
kernel_size,
strides=1,
padding='valid',
output_padding=None,
data_format=None,
dilation_rate=1,
activation=None,
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
**kwargs
)
二维卷积Conv2D及其反卷积Conv2DTranspose :
tf.keras.layers.Conv2D(
filters,
kernel_size,
strides=(1, 1),
padding='valid',
data_format=None,
dilation_rate=(1, 1),
groups=1,
activation=None,
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
**kwargs
)
tf.keras.layers.Conv2DTranspose(
filters,
kernel_size,
strides=(1, 1),
padding='valid',
output_padding=None,
data_format=None,
dilation_rate=(1, 1),
activation=None,
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
**kwargs
)
三维卷积Conv3D及其反卷积Conv3DTranspose:
tf.keras.layers.Conv3D(
filters,
kernel_size,
strides=(1, 1, 1),
padding='valid',
data_format=None,
dilation_rate=(1, 1, 1),
groups=1,
activation=None,
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
**kwargs
)
tf.keras.layers.Conv3DTranspose(
filters,
kernel_size,
strides=(1, 1, 1),
padding='valid',
output_padding=None,
data_format=None,
dilation_rate=(1, 1, 1),
activation=None,
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
**kwargs
)
https://www.tensorflow.org/api_docs/python/tf/keras/initializers 其权重的初始化主要是设置kernel_initializer,它的设置可以在上面网页上选择。
常见的初始化方法
- 随机初始化
随机初始化从均值为0,标准差是1的高斯分布中取样,使用一些很小的值对参数W进行初始化。 - 标准初始化
权重参数初始化从区间均匀随机取值。即在(-1/√d,1/√d)均匀分布中生成当前神经元的权重,其中d为每个神经元的输入数量。
介绍一下正态分布随机初始化和均匀分布随机初始化,分别是是针对连续性问题和随机性问题的随机初始化。基于权重特点初始化的特征,重点介绍一下这两种初始化方法:
- Xavier / Glorot正态分布初始化
Glorot 正态分布初始化器,也称为 Xavier 正态分布随机初始化器。它从以 0 为中心,标准差为
s
t
d
=
(
2
/
(
f
a
n
i
n
+
f
a
n
o
u
t
)
)
{\rm std} = \sqrt{(2 / ({\rm fan}_{in} + {\rm{fan}}_{out}))}
std=(2/(fanin?+fanout?))
? 的截断正态分布中抽取样本, 其中
f
a
n
i
n
{\rm{fan}}_{in}
fanin? 是权值张量中的输入单位的数量,
f
a
n
o
u
t
{\rm fan}_{out}
fanout? 是权值张量中的输出单位的数量。
import tensorflow as tf
initializer = tf.keras.initializers.glorot_normal(seed = 123)
values = initializer(shape=(3, 3))
print(values)
print:
tf.Tensor(
[[ 0.04128221 -0.1245332 0.23356739]
[ 0.33747318 0.17235029 -0.2930978 ]
[-0.5966269 0.07215903 -0.3348947 ]], shape=(3, 3), dtype=float32)
- Xavier / Glorot 标准分布
Glorot 均匀分布初始化器,也称为 Xavier 均匀分布初始化器。它从
[
?
l
i
m
i
t
,
l
i
m
i
t
]
[-limit,limit]
[?limit,limit] 中的均匀分布中抽取样本, 其中
l
i
m
i
t
limit
limit 是
(
6
/
(
f
a
n
i
n
+
f
a
n
o
u
t
)
)
\sqrt{(6 / ({\rm fan}_{in} + {\rm fan}_{out}))}
(6/(fanin?+fanout?))
?, 其中
f
a
n
i
n
{\rm fan}_{in}
fanin? 是输入神经元的个数, ${\rm fan}_{out} 是输出的神经元个数。
import tensorflow as tf
initializer = tf.keras.initializers.glorot_uniform(seed = 123)
values = initializer(shape=(3, 3))
print(values)
输出:
tf.Tensor(
[[-0.04798412 -0.22223973 -0.9824271 ]
[-0.57410717 -0.79084826 -0.6723347 ]
[-0.54534245 -0.14903617 0.22151732]], shape=(3, 3), dtype=float32)
该方法的基本思想是各层的激活值和梯度的方差在传播过程中保持一致。即初始化通过从均值为零和特定方差的分布中提取权重来初始化网络中的权重。 该初始化的缺点: 因为Xavier的推导过程是基于几个假设的,其中一个是激活函数是线性的,这并不适用于ReLU,sigmoid等非线性激活函数;另一个是激活值关于0对称,这个不适用于sigmoid函数和ReLU函数它们不是关于0对称的。
- He Normal初始化
Kaiming初始化,也称之为He初始化,也称之为msra初始化,出自大神何凯明只手。这种初始化方法在He-et-al于2015年提交的论文中广为人知,并且类似于Xavier初始化,系数乘以2。因为Xavier / Glorot是线性的激活函数,因此它并不善于处理非线性问题。在这种方法中,权重的初始化要考虑到前一层的大小,这有助于更快,更有效地实现成本函数的全局最小值。权重仍然是随机的,但范围取决于前一层的大小神经元。这提供了受控的初始化,因此更快,更有效的梯度下降。 - He 正态分布初始化器
它从以 0 为中心,标准差为
s
t
d
=
(
2
/
f
a
n
i
n
)
{\rm std} = \sqrt{(2 / {\rm fan}_{in})}
std=(2/fanin?)
? 的截断正态分布中抽取样本, 其中
f
a
n
i
n
{\rm fan}_{in}
fanin?权值张量中的输入单位的数量。
import tensorflow as tf
initializer = tf.keras.initializers.he_normal(seed = 123)
values = initializer(shape=(3, 3))
print(values)
输出:
tf.Tensor(
[[ 0.7270484 -0.86636555 0.6590073 ]
[ 1.6904085 -0.21603663 -1.3408647 ]
[-1.0661149 -0.16703579 -0.8237521 ]], shape=(3, 3), dtype=float32)
- He 标准化初始化
它从
[
?
l
i
m
i
t
,
l
i
m
i
t
]
[-limit,limit]
[?limit,limit] 中的均匀分布中抽取样本, 其中
l
i
m
i
t
limit
limit 是
(
6
/
f
a
n
i
n
)
\sqrt{(6 / {\rm fan}_{in})}
(6/fanin?)
?, 其中
f
a
n
i
n
{\rm fan}_{in}
fanin? 是权值张量中的输入单位的数量。
import tensorflow as tf
initializer = tf.keras.initializers.he_uniform(seed = 123)
values = initializer(shape=(3, 3))
print(values)
结果:
tf.Tensor(
[[-0.06785977 -0.31429446 -1.3893617 ]
[-0.81191015 -1.1184283 -0.9508248 ]
[-0.7712307 -0.21076894 0.31327283]], shape=(3, 3), dtype=float32)
BN 初始化
BN初始化不同于上面说的初始化情况,并不是在初始的时候给一个初始值,它的存在主要是为了防止梯度消失,它作用在每层网络中。具体是随着网络层数的增加,分布逐渐发生偏移,之所以收敛慢,是因为整体分布往非线性函数取值区间的上下限靠近。这会导致反向传播时梯度消失。BN就是通过规范化的手段,把每层神经网络任意神经元这个输入值的分布强行拉回到均值0方差1的标准正态分布,使得激活输入值落入非线性函数中比较敏感的区域。可以让梯度变大,学习收敛速度快,能大大加快收敛速度。
更多的初始化方法可以见http://121.199.45.168:10006/deeplearning/section1/
总结
- 数据模型是非线性的情况时,激活函数一般选择relu,elu等,使用 He Normal 初始化效果更好。
- 数据模型是线性的情况时,激活函数一般选择sigmoid等,使用 Xavier初始化效果更好。
- BN初始化可以作用在每一层上,是一种规范化的手段,可以将每层激活函数输出的值重新做均值为0,反差为1的标准正态分布,解决梯度消失的问题,也在防止过拟合上有很明显的效果。
|