每日一篇小论文 ---- Weight Normalization
每日一篇小论文 ---- Weight Normalization
@每日一篇小论文----arXiv:1602.07868v3
Weight Normalization
我们提出权重归一化:神经网络中权重向量的重新参数化,将那些权重向量的长度与它们的方向分离。通过以这种方式重新参数化,我们改进了优化问题的条件,并加快了随机梯度下降的收敛速度。我们的重新参数化受到批量标准化的启发,但不会在批处理中的示例之间引入任何依赖关系。这意味着我们的方法也可以成功地应用于诸如LSTM之类的递归模型以及诸如深度强化学习或生成模型的噪声敏感应用,其中批量归一化不太适合。虽然我们的方法更简单,但它仍然提供了全批量标准化的大部分加速。此外,我们的方法的计算开销较低,允许在相同的时间内采取更多的优化步骤。我们证明了我们的方法在监督图像识别,生成建模和深度强化学习中的应用的有用性。
核心思想
对方向权重做归一化,并添加scalar,
即:w=g∣∣v∣∣vw = \frac{g}{||v||}vw=∣∣v∣∣gv
意义
减弱因数据集不平均,而对于权重产生的影响
参考程序
class _WNConv(convolutional_layers._Conv):
def __init__(self, *args, **kwargs):
self.weight_norm = kwargs.pop('weight_norm')
super(_WNConv, self).__init__(*args, **kwargs)
def build(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape)
if self.data_format == 'channels_first':
channel_axis = 1
else:
channel_axis = -1
if input_shape[channel_axis].value is None:
raise ValueError('The channel dimension of the inputs '
'should be defined. Found `None`.')
input_dim = input_shape[channel_axis].value
kernel_shape = self.kernel_size + (input_dim, self.filters)
kernel = self.add_variable(name='kernel',
shape=kernel_shape,
initializer=self.kernel_initializer,
regularizer=self.kernel_regularizer,
constraint=self.kernel_constraint,
trainable=True,
dtype=self.dtype)
# weight normalization
if self.weight_norm:
g = self.add_variable(name='wn/g',
shape=(self.filters,),
initializer=init_ops.ones_initializer(),
dtype=kernel.dtype,
trainable=True)
self.kernel = tf.reshape(g, [1, 1, self.filters]) * nn_impl.l2_normalize(kernel, [0, 1])
else:
self.kernel = kernel
if self.use_bias:
self.bias = self.add_variable(name='bias',
shape=(self.filters,),
initializer=self.bias_initializer,
regularizer=self.bias_regularizer,
constraint=self.bias_constraint,
trainable=True,
dtype=self.dtype)
else:
self.bias = None
self.input_spec = base.InputSpec(ndim=self.rank + 2,
axes={channel_axis: input_dim})
self._convolution_op = nn_ops.Convolution(input_shape,
filter_shape=self.kernel.get_shape(),
dilation_rate=self.dilation_rate,
strides=self.strides,
padding=self.padding.upper(),
data_format=utils.convert_data_format(
self.data_format,
self.rank + 2))
self.built = True
以下内容参考:https://www.wengbi.com/thread_79528_1.html
为什么wn有效?
1.考虑以下情形:假设我们有60亿个id,每个id有1W张不同场景下的人脸图片,我们把这个做成一个训练集,直接用softmax去学习其分布,我们能不能说我们学到了全世界的人脸分布?答案是可以的,因为我们的test set再大,其id也不会超过全球的总人数,加之我们每个id下面的人脸图片足够多(1W)张,我们有理由确信这个分布是可信的。
2.考虑以下情形:假设现在我们只有3个id,其中第一,第二个id下面有100张很相似的人脸图片,第三个id下面只有1张。现在我们用softmax去学习其分布,并用一个2维向量表示学到的特征,那么它的分布应该是下面这样的(二维可视化):
可以自己模拟一下,会发现这种情况下的softmax loss是最小的。也就是说,由于id1和id2的图片数量远大于id3的图片数量,导致id3在分类的时候基本处于一个随波逐流的状态。那么id3肯定不乐意的,同样都是人,为什么差距就那么大呢?没办法,谁让你底下只有1张图片呢?
但是我们自己肯定是有个判断的:id3是绝对可以拿出100张人脸图片的,只是在这个训练集中他没有拿出100张,他只拿出了1张。
这就好比我们丢硬币猜正反面,我们丢了10次硬币,其中有9次是正面,1次是背面。那么我们会预测下一次是正面的概率是90%吗?不是,我们知道概率是50%。相比于贝叶斯的先验概率,我们有一个更强的先验概率。
对于人脸同样如此,我们做Weight Normalization,正是因为我们可以主观上判定:每一个人都可以拿出同样多的人脸图片。
那么做了Weight Normalization,上面的可视化会变成这样的:
是不是瞬间就感觉合理多了。
3.上面这个例子还缺少一个充分条件,那就是id的weight长度是和id下面的人脸图片数量是成正比的。关于这一点,Guo Yandong在其论文里面做了详细的实验:
论文: One-shot Face Recognition by Promoting Underrepresented Classes
作者自己建了一个人脸base数据集,也就是我之前提到的MS_20K,包括20K个id,每个id下面有50-100张人脸图片;然后作者建立了一个novel数据集,包括1K个id,每个id下面有20张图片,作者称其为low shot learning,也就是为了探究样本不均衡的问题。
深度学习网络加速器Weight Normalization_WN
前面我们学习过深度学习中用于加速网络训练、提升网络泛化能力的两种策略:Batch Normalization(Batch Normalization)和Layer Normalization(LN)。今天讨论另一种与它们类似的策略:Weight Normalization(Weight Normalization)。Weight Normalization是Batch Normalization的一种变体,与Batch Normalization最大不同点:对神经网络的权值向量W进行参数重写Reparameterization。
Reparameterization:机器学习/深度学习中常用的一种优化策略,Kingma在提出变分自动编码器(Variational Auto-Encoding,VAE)时,用于神经网络中采样的node进行梯度反向传播的一种方法。简单一句话概括一下Reparameterization:用一个简单的参数为Theta分布来逼近一个稍复杂的分布,通过重写目标函数Objective的期望,使目标函数变得更加容易计算的一种方法,下一期将深入介绍。
1、Weight Normalization与Batch Normalization对比
Weight Normalization和Batch Normalization都属于参数重写(Reparameterization)的方法,只是采用的方式不同,Weight Normalization是对网络权值W进行normalization,因此也称为Weight Normalization;Batch Normalization是对网络某一层输入数据进行normalization。。Weight Normalization相比Batch Normalization有以下三点优势:
1、Weight Normalization通过重写深度学习网络的权重W的方式来加速深度学习网络参数收敛,没有引入minbatch的依赖,适用于RNN(LSTM)网络(Batch Normalization不能直接用于RNN,进行normalization操作,原因在于:1、RNN处理的Sequence是变长的;2、RNN是基于time step计算,如果直接使用Batch Normalization处理,需要保存每个time step下,mini btach的均值和方差,效率低且占内存)。
2、Batch Normalization基于一个mini batch的数据计算均值和方差,而不是基于整个Training set来做,相当于进行梯度计算式引入噪声。因此,Batch Normalization不适用于对噪声敏感的强化学习、生成模型(Generative model:GAN,VAE)使用。相反,Weight Normalization对通过标量g和向量v对权重W进行重写,重写向量v是固定的,因此,基于Weight Normalization的Normalization可以看做比Batch Normalization引入更少的噪声。
3、不需要额外的存储空间来保存mini batch的均值和方差,同时实现Weight Normalization时,对深度学习网络进行正向信号传播和反向梯度计算带来的额外计算开销也很小。因此,要比采用Batch Normalization进行normalization操作时,速度快。
但是, Weight Normalization不具备Batch Normalization把网络每一层的输出Y固定在一个变化范围的作用。因此,采用Weight Normalization进行Normalization时需要特别注意参数初始值的选择。
2、Weight Normalization怎么实现的
对深度学习网络权值W进行normalization的操作公式如下:
方法很简单,通过一个标量g和一个向量V对权重向量W进行尺度变换。标量g的值一般为||W||,即权重W的大小。
此时的深度学习网络权值的梯度计算公式为:
梯度计算公式可以用另外一种方式来表示:
可见,可以通过向量V的大小||V||的变化对权重W进行norm约束,使得网络参数训练相对Learning rate更加鲁棒,即可以选择一个更大的学习速率来加速网络训练。
3、Weight Normalization和Batch Normalization关系
可以把Batch Normalization表示成如下公式形式:
其中,u(t)和v(t)分别是t的均值和方差,t = v / ||v|| * x。可见,当网络只有一层且每一层的输入x服从0均值且方差为1的标准正太分布时,u(t)= 0,v(t) = 1,此时,使用Weight Normalization和Batch Normalization进行Normalization起到的是一样的效果。
4、参考论文
[1] Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift
[2] Weight Normalization: A Simple Reparameterization to Accelerate Training of Deep Neural Networks
[3] Layer Normalization
更多深度学习在NLP方面应用的经典论文、实践经验和最新消息,欢迎关注微信公众号“深度学习与NLP”或“DeepLearning_NLP”或扫描二维码添加关注。