神经网络中的Normalization



  • 为什么需要归一化

    通过使用BN,每个神经元的激活变得(或多或少)高斯分布,即它通常中等活跃,有时有点活跃,罕见非常活跃。协变量偏移是不满足需要的,因为后面的层必须适应分布类型的变化

    神经网路学习过程本质上就是为了学习数据分布,如果训练数据与测试数据的分布不同,网络的泛华能力就会严重减低。

    网络前面层训练参数的更新将导致后面层输入数据分布的变化,必然会引起后面每一层输入数据分布的改变。而且前面微小的变化,经过网络的传输会逐渐把变化累计放大。训练过程中网络中间层数据分布的改变称为Internal Covariate Shift。BN就是为了解决在训练过程中,中间层数据分布发生改变的情况。

    Batch Normalization

    BN步骤

    • 求每一个batch的均值
    • 求每一个batch的方差
    • 对该batch的数据减去均值再除以方差,得到0-1分布

    以上这个处理对于在-1~1之间的梯度变化不大的激活函数,效果不仅不好,反而更差。例如sigmoid函数在-1~1之间几乎是线性,BN变化后就没有达到非线性变换的目的,对于relu,效果会更差。所以要增加下面的缩放加移位操作,将分布从0移开。

    • 尺度变化和偏移,将xi乘以γ调整数值大小,再加上β增加偏移后得到yi,这里的γ是尺度因子,β是平移因子。由于归一化后的xi基本会被限制在正态分布下,使得网络的表达能力下降。为解决该问题,我们引入两个新的参数:γ,β。 γ和β是在训练时网络自己学习得到的
      3b26f85318e84f319541b9e603310e28.jpeg

    预测时的均值和方差怎么求

    在训练时,我们会对同一批的数据的均值和方差进行求解,进而进行归一化操作。但是对于预测时我们的均值和方差怎么求呢?比如我们预测单个样本时,那还怎么求均值和方法呀!其实是这种样子的,对于预测阶段时所使用的均值和方差,其实也是来源于训练集。比如我们在模型训练时我们就记录下每个batch下的均值和方差,待训练完毕后,我们求整个训练样本的均值和方差期望值,作为我们进行预测时进行BN的的均值和方差。但是,当训练数据和测试数据分布有差别是时,训练机上预计算好的数据并不能代表测试数据,这就导致在训练,验证,测试这三个阶段存在inconsistency。

    BN的优点

    • BN能显著提高训练速度
    • 能解决sigmoid严重的梯度消失问题,能将输出从梯度饱和区拉到非饱和区。
    • 使用BN,优化器的选择不会产生显著差异
    • 使用BN后,就不用太依赖drop out和L2正则。可以选择更小的L2正则约束参数,因为BN本身具有提高网络泛华能力的特性。

    BN的缺点

    • BN特别依赖batch size,当batch size非常小的时候,BN的效果就非常不理想了。所以为了使用BN,尽量避免太小的batch size
    • BN对处理序列化数据的网络比如RNN不太适用。
    • BN只能在训练的时候用,预测的时候不是批量输入。
    • 对于数据分布极不平衡的二分类测试任务,BN会破坏性能。

    BN有momentum参数?
    momentum: Momentum for the moving average. 暂时还没理解这个参数的作用

    tf.layers.batch_normalization(x,
                          momentum=momentum, # ???
                          epsilon=epsilon,
                          scale=True,
                          training=train,
                          name=name)
    

    Layer Normalization

    LN的操作类似于将BN做了一个“转置”,对同一层网络的输出做一个标准化。注意,同一层的输出是单个图片的输出,比如对于一个batch为32的神经网络训练,会有32个均值和方差被得出,每个均值和方差都是由单个图片的所有channel之间做一个标准化。这么操作,就使得LN不受batch size的影响。同时,LN可以很好地用到序列型网络如RNN中。同时,LR在训练过程和inference过程都会有,这就是和BN很大的差别了

    Kaiming ECCV2018的paper里,实实在在拿LN和BN做了比较,结果是在较大batch size的时候BN的表现比LN好很多。BN也没那么好欺负的,不然怎么大大小小的主流网络都在用BN呢。

    Group Normalization

    101604hs5or3eelrldd5d5.jpg
    从左到右依次是BN,LN,IN,GN

    深度网络中的数据维度一般是[N, C, H, W]或者[N, H, W,C]格式,N是batch sizeH/Wfeature的高/宽,C是featurechannel,压缩H/W至一个维度,其三维的表示如上图,假设单个方格的长度是1,那么其表示的是[6, 6,*, * ]

    上图形象的表示了四种norm的工作方式:
    BN在batch的维度上norm,归一化维度为[N,H,W],对batch中对应的channel归一化;
    LN避开了batch维度,归一化的维度为[C,H,W]
    IN 归一化的维度为[H,W]
    而GN介于LN和IN之间,其首先将channel分为许多组(group),对每一组做归一化,及先将feature的维度由[N, C, H, W]reshape为[N, G,C//G , H, W],归一化的维度为[C//G , H, W]

    由此可以看出,GN和BN是有很多相似之处的,代码相比较BN改动只有一两行而已,论文给出的代码实现如下:

    def GroupNorm(x, gamma, beta, G, eps=1e-5):
        # x: input features with shape [N,C,H,W]
        # gamma, beta: scale and offset, with shape [1,C,1,1]
        # G: number of groups for GN
        N, C, H, W = x.shape
        x = tf.reshape(x, [N, G, C // G, H, W])
        mean, var = tf.nn.moments(x, [2, 3, 4], keep dims=True)
        x = (x - mean) / tf.sqrt(var + eps)
        x = tf.reshape(x, [N, C, H, W])
        return x * gamma + beta
    

    其中beta 和gama参数是norm中可训练参数,表示平移和缩放因子

    为什么GN会有效

    传统角度来讲,在深度学习没有火起来之前,提取特征通常是使用SIFT,HOG和GIST特征,这些特征有一个共性,都具有按group表示的特性,每一个group由相同种类直方图的构建而成,这些特征通常是对在每个直方图(histogram)或每个方向(orientation)上进行组归一化(group-wise norm)而得到。

    而更高维的特征比如VLAD和Fisher Vectors(FV)也可以看作是group-wise feature,此处的group可以被认为是每个聚类(cluster)下的子向量sub-vector。

    从深度学习上来讲,完全可以认为卷积提取的特征是一种非结构化的特征或者向量,拿网络的第一层卷积为例,卷积层中的的卷积核filter1和此卷积核的其他经过transform过的版本filter2(transform可以是horizontal flipping等),在同一张图像上学习到的特征应该是具有相同的分布,那么,具有相同的特征可以被分到同一个group中,按照个人理解,每一层有很多的卷积核,这些核学习到的特征并不完全是独立的,某些特征具有相同的分布,因此可以被group。

    导致分组(group)的因素有很多,比如频率、形状、亮度和纹理等,HOG特征根据orientation分组,而对神经网络来讲,其提取特征的机制更加复杂,也更加难以描述,变得不那么直观。


 

Copyright © 2018 bbs.dian.org.cn All rights reserved.

与 Dian 的连接断开,我们正在尝试重连,请耐心等待