深度学习激活函数与正则化问题

深度学习激活函数与正规化–潘登的深度学习笔记

[En]

Deep Learning Activation function and regularization-Pandon’s Deep Learning Notes

文章目录

梯度消失问题(Vanishing Gradients)

在梯度下降过程中,随着算法反馈到前几层,梯度会越来越小,最后不会有变化,此时可能不会收敛到更好的解,这就是梯度消失的问题,深度学习就会出现梯度不稳定的问题。不同的层次以不同的速度学习。

[En]

In the gradient descent, as the algorithm is fed back to the first few layers, the gradient will become smaller and smaller, and finally, there will be no change, which may not converge to a better solution at this time, which is the problem of gradient disappearance, and deep learning suffers from unstable gradients. Different layers learn at different speeds.

如果我们看sigmoid激活函数,当输入比较大,不管正负,将会饱和在 0 或 1,这样梯度就是 0,因此当反向传播开始,它几乎没有梯度传播回神经网络,所以就会导致只更改高的几 层,低的几层不会变化

深度学习激活函数与正则化问题

; Relu的缺点

选择 ReLU 更多因为对于正数时候不饱和,同时因为它计算速度快 但是不幸的是,ReLU 激活函数不完美,有个问题是 dying ReLU,在训练的时候一些神经元死了,当它们输出小于 0,经过ReLU就会变成0,不管以后反向传播的再多,最终改变w也是0

解决方案: Leaky ReLU
max ⁡ ( α ∗ z , z ) , α = 0.01 \max(\alpha * z,z), \alpha =0.01 max (α∗z ,z ),α=0 .0 1

自己封装 Leaky ReLU

def leaky_relu(z,name=None):
    return tf.maximun(0.01*z,z,name=name)

hidden1 = fully_connected(X,n_hidden1,activitation_fn=leaky_relu)

其他Relu变形

  • RReLU,Random,α \alpha α 是一个在给定范围内随机取值的数在训练时,固定的平均值在测试时,过拟合时可以试试
  • PReLU,Parametric,α \alpha α 是一个在训练过程中需要学习的参数,它会被修改在反向传播中,适合大数据集
  • ELU,exponential,计算梯度的速度会慢一些,但是整体因为没有死的神经元,整体收敛快,超参数 0.01

ELU 可以在tansorflow中直接调用

hidden1 = fully_connected(X,n_hidden1,activation_fn=tf.nn.elu)

参数初始化问题

深度学习模型训练的过程本质是对 weight(即参数 W)进行更新,这需要每个参数有相应的初始值。有人可能会说:”参数初始化有什么难点?直接将所有 weight 初始化为 0 或者初始化为随机数!” 对一些简单的机器学习模型,或当 optimization function 是 convex function 时,这些简单的方法确实有效。然而对于深度学习而言,非线性函数被疯狂叠加,non-convex function,如何选择参数初始值便成为一个值得探讨的问题 — 其本质是初始参数的选择应使得 objective function 便于被优化。事实上,在学术界这也是一个被 actively 研究的领域。

pre-training

不想从零开始训练神经网络时,我们往往选择一个已经训练好的在任务 A 上的模型(称为 pre-trained model),将其放在任务 B 上做模型调整(称为 fine-tuning)

random initialization

随机初始化是目前很多人经常使用的一种方法,但它有缺点。一旦随机分布选择不当,就会导致网络优化陷入困境。

[En]

Random initialization is a method often used by many people at present, but it has drawbacks. Once the random distribution is not selected properly, it will lead to network optimization in trouble.

以 tanh 神经网络为例,查看激活值和梯度的分布情况。

深度学习激活函数与正则化问题

可以看出,激活值的方差逐层减小反向传播的梯度的分布(相对于状态的梯度):

[En]

It can be seen that the variance of the activation value decreases layer by layer the distribution of the gradient of back propagation (with respect to the gradient of the state):

深度学习激活函数与正则化问题

随着层数的增加,渐变会越来越接近0,渐变会消失。

[En]

With the increase of the number of layers, the gradient will get closer and closer to 0, and the gradient will disappear.

; 代码验证

我们创建了一个 10 层的神经网络,非线性变换为 tanh,每一层的参数都是随机正态分布,均值为 0,标准差为 0.01。

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

data = tf.constant(np.random.randn(2000, 800))
layer_sizes = [800 - 50 * i for i in range(0,11)]
num_layers = len(layer_sizes)
fcs = []
fig, axs = plt.subplots(2, 5, figsize=(15, 6), sharey=True)
for i in range(0, num_layers - 1):
    X = data if i == 0 else fcs[i - 1]
    node_in = layer_sizes[i]
    node_out = layer_sizes[i + 1]
    W = tf.Variable(np.random.randn(node_in, node_out)) * 0.01
    fc = tf.matmul(X, W)
    fc = tf.nn.tanh(fc)
    fcs.append(fc)
    axs[i//5,i%5].hist(fc.numpy()[:,1])

fig.show()

深度学习激活函数与正则化问题

注意横坐标值,如果都固定为[-1,1]区间,那么最终就会看不见输出。随着层数的增加,我们看到输出值迅速向 0 靠拢,在后几层中,几乎所有的输出值都 很接近 0!回忆优化神经网络的 back propagation 算法,根据链式法则,gradient 等于当前函数的 gradient 乘以后一层的 gradient,这意味着输出值计算 gradient 中的乘法因子,直接导致 gradient 很小,使得参数难以被更新!

让我们增加初始值:平均值为0,标准差为1。

[En]

Let’s increase the initial value: the mean is 0 and the standard deviation is 1.

深度学习激活函数与正则化问题

几乎所有的值集中在-1 或 1 附近,神经元 saturated 了!注意到 tanh 在-1 和 1 附近 的 gradient 都接近 0,这同样导致了 gradient 太小,参数难以被更新。

Xavier initialization

Xavier 初始化的基本思想是保持输入和输出的方差一致,这样就避免了所有输出值都趋向于 0。注意,为了问题的简便,Xavier 初始化的推导过程是基于线性函数的,但是它在一些非线性神经元中也很有效

激活函数采用均匀分布随机,区间[-r,r]采用正太分布随机,均值为0sigmoid
r = 6 n i n p u t s + n o u t p u t s r=\sqrt{\frac{6}{n_{inputs}+n_{outputs}}}r =n i n p u t s ​+n o u t p u t s ​6 ​​σ = 2 n i n p u t s + n o u t p u t s \sigma=\sqrt{\frac{2}{n_{inputs}+n_{outputs}}}σ=n i n p u t s ​+n o u t p u t s ​2 ​​

tanh
r = 4 6 n i n p u t s + n o u t p u t s r=4\sqrt{\frac{6}{n_{inputs}+n_{outputs}}}r =4 n i n p u t s ​+n o u t p u t s ​6 ​​σ = 4 2 n i n p u t s + n o u t p u t s \sigma=4\sqrt{\frac{2}{n_{inputs}+n_{outputs}}}σ=4 n i n p u t s ​+n o u t p u t s ​2 ​​

Relu
r = 2 6 n i n p u t s + n o u t p u t s r=\sqrt{2}\sqrt{\frac{6}{n_{inputs}+n_{outputs}}}r =2 ​n i n p u t s ​+n o u t p u t s ​6 ​​σ = 2 2 n i n p u t s + n o u t p u t s \sigma=\sqrt{2}\sqrt{\frac{2}{n_{inputs}+n_{outputs}}}σ=2 ​n i n p u t s ​+n o u t p u t s ​2 ​​

代码验证

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

data = tf.constant(np.random.randn(2000, 800))
layer_sizes = [800 - 50 * i for i in range(0,11)]
num_layers = len(layer_sizes)
fcs = []
fig, axs = plt.subplots(2, 5, figsize=(15, 6), sharey=True)
for i in range(0, num_layers - 1):
    X = data if i == 0 else fcs[i - 1]
    node_in = layer_sizes[i]
    node_out = layer_sizes[i + 1]
    W = tf.Variable(np.random.randn(node_in, node_out)) * np.sqrt(2/(node_in+node_out))
    fc = tf.matmul(X, W)
    fc = tf.nn.tanh(fc)
    fcs.append(fc)
    axs[i//5,i%5].hist(fc.numpy()[:,1])
    axs[i//5,i%5].set_xlim([-1,1])

fig.show()

深度学习激活函数与正则化问题

输出值在很多层之后依然保持着良好的分布,这很有利于我们优化神经网络!之前谈到 Xavier initialization 是在线性函数上推导得出,这说明它对非线性函数并不具有普适性,所以这个例子仅仅说明它对 tanh 很有效,那么对于目前最常用的 ReLU 神经元呢?

W = tf.Variable(np.random.randn(node_in, node_out)) * np.sqrt(4/(node_in+node_out))

fc = tf.nn.relu(fc)

深度学习激活函数与正则化问题

前面看起来不错,但后一种趋势越来越接近0。

[En]

The front looks good, but the latter trend is getting closer and closer to 0.

对参数初始化问题的总结

一般来说,参数的初始化和激活函数的选择都只能缓解梯度消失的症状,而不能解决梯度消失的问题。

[En]

Generally speaking, both the initialization of parameters and the selection of activation function can only alleviate the symptom of disappearance of gradient, but can not solve the problem of disappearance of gradient.

梯度爆炸

在反向传播过程中,许多梯度都大于1。在链导数规则下,乘法的结果趋于无穷大。根据梯度下降法,在梯度爆炸下迈出一大步,从而走出最优解的区域。

[En]

In the process of back propagation, many gradients are greater than 1. Under the chain derivation rule, the result of multiplication tends to infinity. According to the method of gradient descent, it will take a big step under the gradient explosion, so as to get out of the optimal solution domain.

解决方案

  • 使用梯度截断法: Gradient Clipping
  • 使用L1、L2正则化,使得w变小,进而使得反向传播的时候使得gradient变小(因为链式求导的时候,w也是作为乘积项的,导致梯度爆炸的原因可能是w过大)
  • Batch Normalization,一种归一化手段,主要作用在Activations上面
  • 激活函数也会影响,使用Relu优于tanh和sigmoid
  • w的初始化,如果一开始w的绝对值比较大,更容易偷渡爆炸或者消失
  • 网络Topolopy设计可以在一定程度上解决梯度消失或者爆炸

Normalization

常用的Normalization方法主要有: Batch Normalization(BN,2015 年)、Layer Normalization (LN , 2016 年)、 Instance Normalization ( IN , 2017 年 )、Group Normalization(GN,2018 年)。它们都是从激活函数的输入来考虑、做文章的,以不同的方式对激活函数的输入进行 Norm 的。

我们将输入的 feature map shape 记为[N, C, H, W],其中 N 表示 batch size,即 N
个样本;C 表示通道数;H、W 分别表示特征图的高度、宽度。这几个方法主要的区别就是在:

  1. BN 是在 batch 上,对 N、H、W 做归一化,而保留通道 C 的维度。BN 对较小的
    batch size 效果不好。BN 适用于固定深度的前向神经网络,如 CNN,不适用于 RNN;
  2. LN 在通道方向上,对 C、H、W 归一化,主要对 RNN 效果明显
  3. IN 在图像像素上,对 H、W 做归一化,用在风格化迁移
  4. GN 将 channel 分组,然后再做归一化

深度学习激活函数与正则化问题

; Batch Normalization

BN的操作是这样的: 取一个特定的Batch,把这一个Batch中的每个图片的某个通道,作为一个归一化的对象,举例来说[ 10 , 3 , 28 , 28 ] [10,3,28,28][1 0 ,3 ,2 8 ,2 8 ]的图片,当取第一个通道作为归一化的对象的时候,会将10幅图片的第一个通道都拿出来,将102828的数据做归一化…

Batch Normalization 是一种巧妙而粗暴的方法来削弱 bad initialization 的影响,我们想要的是在非线性 activation 之前,输出值应该有比较好的分布(例如高斯分布),
以便于 back propagation 时计算 gradient,更新 weight。

主要思想: 针对每个神经元,使数据在进入激活函数之前,沿着通道计算每个 batch 的均值、方差,’强迫’数据保持均值为 0,方差为 1 的正态分布,避免发生梯度消失。

为什么要进行BN

  1. 在深度神经网络训练的过程中,通常以输入网络的每一个 mini-batch 进行训练,这样每个 batch 具有不同的分布,使模型训练起来特别困难。
  2. Internal Covariate Shift (ICS) 问题:在训练的过程中,激活函数会改变各层数据的
    分配,随着网络的深入,这种变化(差异)会越来越大,使得模型特别难训练,收敛速度也会很快。
    [En]

    Distribution, with the deepening of the network, this change (difference) will become larger and larger, making the model particularly difficult to train and converging fast.

    度数很慢,就会出现梯度消失的问题。(也可以理解为病态矩阵问题,只要有一个小的扰动,就会引起很大的变化。)

    [En]

    The degree is very slow, there will be the problem of gradient disappearance. (it can also be understood as a morbid matrix problem, as long as there is a small disturbance, it will cause a great change.)

BN的使用位置

在全连通层或卷积运算之后,在激活功能之前

[En]

After the fully connected layer or convolution operation, before activating the function

BN算法过程

Batch Normalization 将输出值强行做一次 Gaussian Normalization 和线性变换

Input:Values of x over a mini-batch: B = { x 1 , … , m } \mathcal{B} = {x_{1,\ldots,m}}B ={x 1 ,…,m ​}Parameters to be learned: γ , β \gamma,\beta γ,β

Output:{ y i = N B γ , β ( x i ) } {y_i=NB_{\gamma,\beta}(x_i)}{y i ​=N B γ,β​(x i ​)}
μ B ← 1 m ∑ i = 1 m x i σ B 2 ← 1 m ∑ i = 1 m ( x i − μ B ) 2 x ^ i ← x i − μ B σ B 2 + ϵ y i ← γ x ^ i + β ≡ B N γ , β ( x i ) \mu_{\mathcal{B}} \leftarrow \frac{1}{m}\sum_{i=1}^mx_i \ \sigma_{\mathcal{B}}^2 \leftarrow \frac{1}{m}\sum_{i=1}^m(x_i-\mu_{\mathcal{B}})^2 \ \hat{x}i \leftarrow \frac{x_i-\mu{\mathcal{B}}}{\sqrt{\sigma_{\mathcal{B}}^2 + \epsilon}}\ y_i \leftarrow \gamma\hat{x}i + \beta \equiv BN{\gamma,\beta}(x_i)μB ​←m 1 ​i =1 ∑m ​x i ​σB 2 ​←m 1 ​i =1 ∑m ​(x i ​−μB ​)2 x ^i ​←σB 2 ​+ϵ​x i ​−μB ​​y i ​←γx ^i ​+β≡B N γ,β​(x i ​)

Batch Normalization 中所有的操作都是平滑可导,这使得 back propagation 可以有效运行并学到相应的参数γ , β \gamma,\beta γ,β。需要注意的一点是 Batch Normalization 在 training 和testing 时行为有所差别。Training 时μ B \mu_{\mathcal{B}}μB ​ 和σ B \sigma_{\mathcal{B}}σB ​ 由当前 batch 计算得出;在 Testing 时μ B \mu_{\mathcal{B}}μB ​ 和σ B \sigma_{\mathcal{B}}σB ​ 应使用 Training 时保存的均值或类似的经过处理的值,而不是由当前 batch 计算。

加入缩放和平移变量(算法的最后一步)的原因是:保证每一次数据经过归一化后还保留原有学习来的特征,同时又能完成归一化操作,加速训练。 这两个参数是用来学习的参数。

BN的作用

  1. 允许较大的学习率
  2. 减弱对初始化的强依赖性
  3. 保持隐藏层中数值的均值、方差不变,让数值更稳定,为后面网络提供坚实的基础
  4. 有轻微的正则化作用(相当于给隐藏层加入噪声,类似 Dropout)

BN的问题

  1. 每次是在一个 batch 上计算均值、方差,如果 batch size 太小,则计算的均值、方差不足以代表整个数据分布。
  2. batch size 太大:会超过内存容量;需要跑更多的 epoch,导致总训练时间变长;会直接固定梯度下降的方向,导致很难更新

Layer Normlization

举例来说[ 10 , 3 , 28 , 28 ] [10,3,28,28][1 0 ,3 ,2 8 ,2 8 ]的图片,当取第一张图片作为归一化的对象的时候,会将该图片的全部都拿出来,将32828的数据做归一化…

Instance Normlization

举例来说[ 10 , 3 , 28 , 28 ] [10,3,28,28][1 0 ,3 ,2 8 ,2 8 ]的图片,当取第一张图片的第一个通道作为归一化的对象的时候,会将该图片该通道全部都拿出来,将28*28的数据做归一化…

Group Normlization

举例来说[ 10 , 4 , 28 , 28 ] [10,4,28,28][1 0 ,4 ,2 8 ,2 8 ]的图片,先将每一张图片的通道数划分为G份(假设为2),当取第一张图片的第一个份作为归一化的对象的时候,会将该图片该份全部都拿出来,将22828的数据做归一化…

Original: https://blog.csdn.net/weixin_52185313/article/details/123336080
Author: PD我是你的真爱粉
Title: 深度学习激活函数与正则化问题

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/509294/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球