神经网络搭建(一、正则化)

神经网络中的正则化层

神经网络中的正则化层

在神经网络的搭建中,正则化层非常重要,包括BN、LN、IN和GN等。正则化层一般应用在卷积层或者全连接层之后,在激活函数层之前。正则化层稳定了深层网络的训练。

正则化用来解决函数过拟合的问题。为了防止过拟合。我们需要让损失函数和正则化项最小。满足两者最小,可以尝试让损失函数和正则化项的和较小。

L1正则化, 所有特征绝对值之和,记为\left \| W \right \|_{1}

J = J_{0} + L_{1} = \left \| f(x) - y \right \|_{2}^{2} + \alpha \left \| W \right \|_{1}

L2正则化,通常意义上的模,记为\left \| W \right \|_{2}

J = J_{0} + L_{1} = \left \| f(x) - y \right \|_{2}^{2} + \alpha \left \| W \right \|_{2}

L1正则化具备稀疏性。L2正则化可以很好的解决过拟合问题。拟合过程通常都倾向于让权值尽可能小。在使用L2正则化时,W是不断进行减小的,即权重衰减,这样即可得到一个让所有参数都比较小的模型,即可解决过拟合问题。

深度神经网络前向传播中损失函数为:

J(W, b) = \frac{1}{2m} \sum_{i=1}^{m}\left \| a^{L} - y \right \|_{2}^{2}

加入L2正则化后,损失函数如下所示。其中\lambda是正则化参数:

J(W, b) = \frac{1}{2m} \sum_{i=1}^{m}\left \| a^{L} - y \right \|_{2}^{2} + \frac{\lambda }{2m} \sum_{l=2}^{L}\left \| w \right \|_{2}^{2}

归一化

归一化是指将输入映射到 0-1 之间。常用的归一化操作有min-max归一化操作。

\frac{x - min(x)}{max(x) - min(x)}

标准化

标准化是指对输入数据进行预处理,使其具有均值为0,方差为1的高斯分布。BN、LN、IN和GN都属于标准化操作。

CV中的图像输入维度为B(batch) * C(channel) * H(height) * W(width)

BN(Batch Normalization)

BN的提出是为了解决神经网络中的ICS (internal covariate shift) 现象。

ICS是由于神经网络在每一轮训练之后都会改变网络的参数。这样会导致每一层在每一轮训练时的输入会发生改变,这样网络的每一层就要不断地去适应这种输入数据分布的不断变化,导致了网络难以训练。BN的提出用来规范化网络每一层的输入服从同一分布。同时也有paper指出BN之所以能够稳定神经网络的训练是因为引入BN层之后导致整个神经网络所表示的函数变得更加平滑。

直观上理解, BN就是将输入减去均值,除以方差。但是这样做会导致模型的表达能力受到限制。因此引入两个可学习的参数\gamma\beta来进行平移和缩放。

以图象输入为例, 输入为B * C * H * W, BN是针对batch size维度进行标准化操作。在B、H、W维度上进行操作。因此最终得到C个均值和方差。实际上,在训练过程中,程序维持两个变量running_mean和running_var通过滑动窗口的方式保留均值和方差的统计信息。在测试的时候直接使用running_mean和running_var作为均值和方差。

神经网络训练过程的本质就是学习数据分布,如果训练数据和测试数据的分布不同将大大降低网络的泛化能力,因此我们需要在训练开始前对所有数据进行归一化处理。mini-batch针对的是梯度方向更新, BN针对的是层与层之间数据的输入输出分布。

BN的缺点:

  • 同一个batch size的同一个通道拥有同一个mean和var, 如果batch size设置的太小, 计算的均值和方差并不能代表数据的整体分布, 则BN效果下降明显。
  • 对于像素级别图片生成任务而言,BN效果不佳。
  • 不适用batch size = 1的情况
  • 对于利用RNN训练的模型来说, 由于输入的长度不固定, BN无法计算。而且对于文本输入来说,不同的文本输出差异较大, 在batch维度做标准化也是不合理的。

BN的公式:

preview

def Batch_Normalization_Layer(x, gamma, beta, params):
    #x: 输入数据 x.shape = (B, D)
    #gamma: 缩放因子
    #beta: 平移因子
    #params:    running_mean    滑动平均的方式计算均值的统计信息
    #           running_var     滑动平均的方式计算方差
    #           momentum    动量参数
    running_mean = params['running_mean']
    running_var = params['running_var']
    momentum = params['momentum']

    x_mean = x.mean(axis = 0)
    x_var = x.var(axis = 0)
    x_norm = (x - x_mean) / (x_var + 1e-6)

    ret = gamma * x_norm + beta
    running_mean = momentum * x_mean + (1 - momentum) * running_mean
    running_var = momentum * x_var + (1 - momentum) * running_var

    params['running_mean'] = running_mean
    params['running_var'] = running_var

    return ret, params

LN(LayerNorm)

为了解决BN无法在RNN等变长输入的模型中应用,LN被提出。LN也解决了BN中对batch size较大的要求(通常可能会导致较大的内存开销)。LN层是对layer进行归一化的操作。

以图像输入为例, 在C、H、W维度上进行操作,与B无关, 执行之后有B个均值和方差。这也就是说对于单个输入的训练样本而言,LN层仍然适用。LN层被广泛应用在NLP领域。在Transformer模型中大量使用了LN标准化操作。

IN(InstanceNorm)

IN是针对单个样本进行规范化,在H*W的维度进行规范化操作,因此会得到B*C个均值和方差,每个样本的每个channel都拥有自己的均值和方差。

GN(GroupNorm)

训练过程--Batchsize

训练过程--Batchsize大小设置

在使用样本估计梯度的时候,在同等的计算量之下,使用整个样本集的收敛速度要远慢于使用少量样本的情况。即,要想收敛到同一个最优点,使用整个样本集时,虽然迭代次数少,但是每次迭代的时间长,耗费的总时间是大于使用少量样本多次迭代的情况的。在实际工程中,从收敛角度而言,小批量的样本集(mini-batch)是最优的。

在实际问题中,神经网络的loss曲面(以model参数为自变量,以loss值为因变量画出来的曲面)往往是非凸的,这意味着很可能有多个局部最优点,而且很可能有鞍点

样本量少的时候会带来很大的方差,而这个大方差恰好会导致我们在梯度下降到很差的局部最优点和鞍点的时候不稳定,因为大的噪声而跳出了局部最优点。从而去寻找更优的最优点。与之相反,当样本量很多时,方差很小,对梯度的估计要准确和稳定得多,因此反而会在差劲得局部最优点或者鞍点时无法跳出,导致网络收敛在了很差的点上。

因此对于SGD(随机梯度下降)及其改良的一阶优化算法如AdagradAdam等是没问题的,但是对于强大的二阶优化算法如共轭梯度法L-BFGS来说,如果估计不好一阶导数,那么对二阶导数的估计会有更大的误差,这对于这些靠二阶导数算法来说是致命的。对于二阶优化算法,减小batch换来的收敛速度提升远不如引入大量噪声导致的性能下降,因此在使用二阶优化算法时,往往要采用大batch。同时,GPU对2的幂次的batch可以发挥更佳的性能,因此设置成16、32、64、128...时往往要比设置为整10、整100的倍数时表现更优。

batch_size太大容易错过最优点,太小又容易在局部最小点附近梯度下降特别慢,所以很多架构都有一个decay参数,在前期使用较大的batch。

batch size 和 BN

batch size太大则一个epoch update数量少这个缺点,在BN面前似乎没有什么用处。同时BN不能用太小的batch size, 不然mean和variance就发生偏移。对于实际的模型架构,数据分布和数据预处理更为重要。

(BN对于当BatchSize设置太小时效果不佳,对于RNN等动态网络无法有效应用BN)

设置多大的batch_size

SGD算法的batch size并不能无限制的增大。倘若SGD采用较大地batch size时,如果还是使用同样epochs数量进行运算,准确度往往低于batch size较小的场景。对于大批量训练场景,我们需要确保使用较大的batch size训练能够在相同epochs前提下获得与较小batch size相近的测试准确度。我们之所以保持epochs数量不变,从统计学角度来讲,一个epoch代表着算法与整体数据集接触一次;从计算角度来讲,固定epochs数量意味着保证浮点运算次数不变

batch_size 设置的大一些,收敛得快,也就是需要训练的次数少,准确率上升得稳定,但是实际使用起来精度不高。

batch_size 设置的小一些,收敛得慢,可能出现准确率来回震荡,所以还需要将基础学习率降低一些,但是实际使用起来精度较高。

目前实验证实:batch size设置得较小训练出来的模型相对于batch size设置得较大的模型具有更强的泛化能力。在测试集上表现得更好,而batch size太大往往不太work, 而且泛化能力较差。

batch size设置以喂饱硬件为主要目标,只要显卡塞得下,首先挑选大的。

就个人经验而言 batch_size 越大越好

  • 震荡明显减少
  • 收敛速度加快
  • 同样学习率下大batch可以收敛到更好的水平

在模型训练到尾声时,想更精细化地提高成绩(比如论文实验、比赛到最后), 有一个有用地trick, 就是设置batch size为1,即做纯SGD, 慢慢把error磨低。

梯度下降

批量梯度下降(BGD)

批量梯度下降法是最原始的形式, 它是指在每一次迭代时使用所有样本来进行梯度更新。

随机梯度下降(SGD)

随机梯度下降法不同于批量梯度下降,随机梯度下降是每次迭代使用一个样本来对参数进行更新。使得训练速度加快。

小批量梯度下降(MBGD)

小批量梯度下降,是对批量梯度下降以及随机梯度下降的一个折中办法。其思想是每次迭代使用batch_size个样本来对参数进行更新。

猜你喜欢

转载自blog.csdn.net/jiangchao98/article/details/120436610