在机器学习和深度学习研究中,主要目的是使损失值最小。为了尽快做到这一点,有必要根据我们的问题来启动权重。这个问题被称为**"权重初始化"。**我们需要知道的第一件事是,这是一个设计决定。在我们训练网络之前,我们需要初始化所有的权重。权重的初始值会对训练过程产生重大影响。根据深度学习模型在训练过程中的起点,它可以收敛到不规则损失面中任何可能的局部最小值。
让我们一起思考。如果我们把所有的权重都从0开始,从时间和成本上来说都是一个糟糕的选择。还是说全部从0.5开始是有意义的?从错误的权重开始是否会导致梯度下降的爆炸或消失?答案是肯定的!这就是为什么我们需要初始化。让我们来总结一下。
为什么我们需要权重初始化?
- 人工神经网络的学习在很大程度上取决于权重和偏差的初始设置。
- "随机梯度下降 "收敛到局部最小值。
- 避免了梯度消失和爆炸的问题。(太大的初始化会导致梯度爆炸,太小的初始化会导致梯度消失)。
权重初始化技术
- 零初始化
- 随机初始化
- 泽维尔初始化
- H-at-al初始化
- LeCun初始化
让我们更深入地研究它们中的每一个!为了简化问题,让我对每个初始化技术使用相同的基本模型。
model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(64, 32)), tf.keras.layers.Dense(128, activation='relu', kernel_initializer, bias_initializer) ])
1.零初始化
顾名思义,零初始化就是将所有神经网络的权重初始化为0。请注意,这样做的前提是一半的最终权重为正,一半的权重为负。
如果网络的所有权重都被初始化为零,所有的激活都是零,相应的梯度也是零。事实上,即使权重被初始化为任何其他常数也没有关系。在这种情况下,激活可能不是零,但它们仍然是相同的。因此,我们可以排除零/常数的初始化。
model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(64, 32)), tf.keras.layers.Dense(128, activation='relu', kernel_initializer='zeros', bias_initializer='zeros') ])
2.随机初始化
当激活函数为Sigmoid时,权重值离0越远,标准差越大,输出值就越偏向于接近0和1,然后就会失去梯度。解决这个问题的方法之一是以小标准差的正态分布来初始化权重。一般来说,初始权重以正态分布(高斯分布)随机初始化,其平均值为0,标准差为0.01,如下所示
# With normal distributionsmodel = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(64, 32)), tf.keras.layers.Dense(128, activation='relu', kernel_initializer='RandomNormal', bias_initializer='zeros') ])'''# With Uniform Distributionsmodel = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(64, 32)), tf.keras.layers.Dense(128, activation='relu', kernel_initializer='RandomUniform', bias_initializer='zeros')'''
3.泽维尔(Glorot)初始化
随机初始化对于深度网络来说很快就会崩溃。其原因是,激活度在几层之后会迅速下降到零(梯度也是如此)。Xavier初始化的目的是初始化权重,使每一层的方差都是相同的。换句话说,每层输出的方差必须等于输入的方差,而且在反向传播中通过各层之前和之后的梯度方差必须相同。
# With normal distributionsmodel = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(64, 32)), tf.keras.layers.Dense(128, activation='relu', kernel_initializer='glorot_normal', bias_initializer='zeros') ])'''# With Uniform Distributionsmodel = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(64, 32)), tf.keras.layers.Dense(128, activation='relu', kernel_initializer='glorot_uniform', bias_initializer='zeros')'''
4.He-at-al初始化
何凯明提出了一种适合ReLU的初始值,以他的名字命名,称为何初始值。他的初始化与Xavier的初始化几乎相似,但与Xavier初始化不同。这种差异与ReLU激活函数的非线性有关,他们对权重使用了不同的缩放系数。
# With normal distributionsmodel = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(64, 32)), tf.keras.layers.Dense(128, activation='relu', kernel_initializer='he_normal', bias_initializer='zeros') ])'''# With Uniform Distributionsmodel = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(64, 32)), tf.keras.layers.Dense(128, activation='relu', kernel_initializer='he_uniform', bias_initializer='zeros')'''
5.LeCun初始化
它也被称为 "高效反推",考虑到每一层的输入和输出的大小。这种方法可用于不一定围绕零对称的激活函数,如双曲切线。它产生的权重是随机选择的数字乘以方差1/(input_layer_size)。
# With normal distributionsmodel = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(64, 32)), tf.keras.layers.Dense(128, activation='relu', kernel_initializer='lecun_normal', bias_initializer='zeros') ])'''# With Uniform Distributionsmodel = tf.keras.models.Sequential([ tf.keras.layers.Flatten(input_shape=(64, 32)), tf.keras.layers.Dense(128, activation='relu', kernel_initializer='lecun_uniform', bias_initializer='zeros')'''
我们如何理解好的初始化?
- 导致训练和测试集上的损失较小。
- 不会使大多数sigmoid/tanh单元饱和。
- 不会使ReLu单元爆炸。
- 各层梯度的大小相似。
如何找到合适的初始化值?
- 激活的平均值应该是零。
- 激活的方差应该在每一层保持相同。
参考文献
- sebastianraschka.com/pdf/lecture…
- machinelearningmastery.com/weight-init…
- networks/#:~:text=Weight%20initialization%20is%20procedure,of%20neural%20network%20model.
- heartbeat.comet.ml/weight-init…
- wandb.ai/sauravmahes…
- medium.com/guidona-sof…
- machinelearningmastery.com/weight-init….
- koreascience.kr/article/JAK…
- web.eecs.umich.edu/~justincj/s…
- sebastianraschka.com/pdf/lecture…
- bigmeca.minesparis.psl.eu/wp-content/…
- www.deeplearning.ai/ai-notes/in…
- www.tensorflow.org/api_docs/py…