查看原文
其他

可视化超参数作用机制(二):权重初始化

Daniel Godoy 论智 2021-09-10
作者:Daniel Godoy编译:weakish

编者按:《纽约客》资深数据科学家Daniel Godoy以可视化的方式,简明清晰地介绍了神经网络常用的权重初始化方案。

图片来源:Jesper Aggergaard (Unsplash)


介绍

这是超参数系列的第二篇。在这篇文章中,我将展示恰当地初始化深度神经网络的权重重要性。我们将从一个朴素的初始化方案开始,并着手解决它的问题,例如梯度消失/爆炸,以(重新)发现两种流行的初始化方案:Xavier / GlorotHe

我假定你了解一些关键概念(激活函数和梯度),我在第一篇里介绍了这些概念。

本文中的示意图由我自己编写的DeepReplay生成,它的GitHub地址为dvgodoy/deepreplay

动机

我想深入理解不同的超参数在训练深度神经网络中的作用,这次我将探索权重初始化

如果你曾经检索过这个主题,很可能接触过一些常用的初始化方案

  • 随机

  • Xavier / Glorot

  • He

如果你再深入一点,你很可能知道,Xavier / Glorot初始化和激活函数tanh搭配使用,而He初始化则和激活函数ReLU搭配使用。

顺便澄清一下,Xavier GlorotYoshua Bengio是Understanding the difficulty of training deep feedforward neural networks(理解训练深度前馈神经网络的困难性)这篇论文的作者,所以这个初始化方法有时被称为Xavier初始化(用了作者的名),有时被称为Glorot初始化(用了作者的姓)。换句话说,Xavier初始化和Glorot初始化是一回事。

澄清了这一点后,我再一次向你发问:你曾经好奇过这些初始化到底是怎么进行的?为什么初始化如此重要?这些初始化方案的区别是什么?我指的不仅是它们定义上的不同,还包括使用不同的初始化方案训练深度神经网络的总体效果的不同!

在深入这些问题之前,我首先要感谢Andre Perunicic,本文中的图形从他的博客文章中受到了很多启发。他的博客的网址是:https://intoli.com/blog/neural-network-initialization/

好,现在开始深入!

配置

我将搭建的模型有5个隐藏层,每层100个神经元,以及典型二元分类任务所用的单输出层(即sigmoid激活函数和二元交叉熵损失函数)。我基于Keras搭建了模型:

  1. from keras.models import Sequential

  2. from keras.layers import Dense

  3. def build_model(n_layers, input_dim, units, activation, initializer):

  4.    if isinstance(units, list):

  5.        assert len(units) == n_layers

  6.    else:

  7.        units = [units] * n_layers

  8.    model = Sequential()

  9.    # 添加第一个隐藏层(参数中指定输入维度)

  10.    model.add(Dense(units=units[0],

  11.                    input_dim=input_dim,

  12.                    activation=activation,

  13.                    kernel_initializer=initializer,

  14.                    name='h1'))

  15.    # 添加剩余的隐藏层

  16.    for i in range(2, n_layers + 1):

  17.        model.add(Dense(units=units[i-1],

  18.                        activation=activation,

  19.                        kernel_initializer=initializer,

  20.                        name='h{}'.format(i)))

  21.    # 添加输出层

  22.    model.add(Dense(units=1, activation='sigmoid', kernel_initializer=initializer, name='o'))

  23.    # 编译模型

  24.    model.compile(loss='binary_crossentropy', optimizer='sgd', metrics=['acc'])

  25.    return model

注意,请确保你用的是Keras 2.0.0以上版本——旧版本生成的权重有问题,方差比预期的低。

模型架构

输入

输入为从一个十维球中抽取的1000个随机数据点(这听起来比实际上酷炫,你可以将它想象成由1000个样本组成的数据集,每个样本有10个特征),这些数据点满足均值为零单位标准差

在数据集中,球半径一半以内的数据点为负面情形(0),剩余数据点为正面情形(1)

朴素初始化

开始,我们将使用sigmoid激活函数和随机初始化的权重。这一方案训练比较困难,收敛缓慢,结果不好

但是,为什么?

回到之前的步骤,我们从一个正态分布(均值为零,单位标准差)中抽取随机值,然后乘以一个小数字,比如0.01。结果将是一个标准差接近0.01的权重集。这导致了一些问题。

略微深入(仅仅略微深入,我承诺!)这是一个不好的初始化方案的数学原因前,让我首先展示下我们的模型使用sigmoid激活函数的结果:

绘制以上图形的代码见此:

https://gist.github.com/dvgodoy/3a2909b23669790ddcc527b43b12c5ee

这看起来不好,对吧?你可以指出所有不好的地方吗?

  • Z值(还记得吗,Z值是应用激活函数之前的输出)和激活均处于一个狭窄的区间

  • 梯度基本为

  • 示意图左侧的诡异分布是怎么回事?!

很不幸,如果我们选择尝试训练这个网络,这个网络很可能短时期内学不到任何东西。为什么?因为梯度消失了

而我们甚至还没有开始训练过程!这是Epoch 0!让我们看看,目前为止发生了什么:

  1. 朴素的方案(示意图右上方)初始化了权重

  2. 网络的前向传播和每层生成的Z值(示意图左上方)以及激活(示意图左下方)使用了1000个样本(示意图没有把输出层放进去)。

  3. 根据真实标签计算损失,并在网络中反向传播,为所有层生成梯度(示意图右下方)。

上面就是网络的单次传播过程。

接着,我们应该更新权重重复这一过程,对吧?但是,等一下……如果权重基本上是,那更新过的权重基本上会是一样的,对吧?

意味着什么?这意味着我们的网络接近无用的边缘,因为在合理的时间内,它无法学习任何东西(即更新权重以进行所需的分类任务)。

欢迎体验这一梯度消失的极端情形!

你可能会想:“是的,没错,标准差太低了,这样低的标准差没法工作。”所以,不如尝试下不同的值,比如,10倍或者100倍

10倍标准差 = 0.10

好,看起来好一点了……Z值激活位于适宜的区间,靠后的隐藏层的梯度有一些改观,但靠前的隐藏层梯度仍然消失

也许再大些可以修正这些梯度,让我们看看……

100倍标准差 = 1.00

好,看起来我们在梯度消失问题上取得了一些进展,因为每层的梯度处于相似的区间。哇!不过……我们同时毁掉Z值激活……,Z值的区间过宽了,迫使激活基本上进入了二值模式

尝试一个不同的激活函数

如果你读过本系列的第一篇文章,你可能会回想起sigmoid激活会有以0.5为中心的基本问题。所以,让我们改用tanh激活函数试试。

在保持使用朴素初始化方案的同时替换sigmoid激活函数为tanh导致了另一种不同的梯度消失情形(也许看起来不像,毕竟所有层的梯度比较相似,但是看下尺度,梯度在最后一层已经消失了!),同时伴随着Z值消失激活消失(明确一下,这两个提法不是正式的术语)!这绝对不是我们该走的路!

让我们看下较大的标准差是什么情况。

在这一设定下,我们可以观察到梯度爆炸问题。看到没有,从最后一个隐藏层反向传播至第一个隐藏层的过程中,梯度越来越大?另外,类似sigmoid激活函数,Z值区间太宽了,导致激活塌缩到大多数值要么是零要么是一的情形。同样,这不好!

我们的冠军是……tanh搭配标准差0.10

为什么会是冠军?让我们查看下它的特性:

  • 首先,梯度所有层相似(同时位于一个适宜的尺度——约为权重的1/20)

  • 其次,Z值位于一个适宜的区间(-1, 1),在所有层上相似(虽然可以观察到一些收缩)

  • 最后,激活没有塌缩到二值模式,并且在所有层上相似(同样,有一些收缩)

也许你已经注意到了,在所有层上相似非常重要!简单来说,这意味着我们可以在网络后面堆叠另一层,然后期望Z值激活梯度分布仍然是相似的。我们肯定希望网络表现出塌缩消失爆炸,不,这不行!

然而,在所有层上相似是结果,而非原因……你大概已经猜到了,关键权重的标准差

所以,我们需要使用尽可能好的标准差初始化方案来抽取随机权重!让我们进入Xavier GlorotYoshua Bengio的世界……

Xavier / Glorot 初始化

Glorot和Bengio设计了一种初始化方案,该方案试图保持前面列出的获胜特性,即梯度Z值激活所有层上相似。换句话说,保持所有层的方差相似

你会问,他们是如何做到这一点的呢?稍等片刻我们将知晓答案,在此之前,我们需要简单温习下方差的基本性质。

简短的温习

假设我们有x值(可能是输入,也可能是之前层的激活值)和W权重。下式给出了两个独立变量之积的方差:

接着,让我们假定xW都满足均值为零。此时上式可以简化为xW方差之积:

有两点值得注意:

  1. 为了满足上式的条件,输入均值须为零,所以总是调整输入的尺度和中心!

  2. sigmoid激活函数造成了一个问题,因为激活值的均值为0.5,而不是零!关于如何补偿这一点,可以参考mnsgrg.com/2017/12/21/xavier-initialization/ 基于以上第二点,我们将坚持使用tanh。现在到了应用所学于一个小例子的时候了,这样我们可以得出和GlorotBengio一样的结论(希望如此!)。

小例子

这个例子由两个隐藏层组成,XY,全连接(我将惯例抛到九霄云外,从而尽可能少地使用数学符号)。

我们只在乎连接这两层的权重,以及激活梯度方差

我们需要经过网络的一次前向传播得到激活;我们需要反向传播得到梯度

同时,为了简化数学,我们将假设激活函数是线性的(而不是tanh),这意味着激活值Z值相等

尽管这也许看起来有点夸张,但tanh的函数图像告诉我们,在区间[-1, 1]tanh差不多是线性的,所以至少在这一区间,所得结果应该是成立的。

tanh激活函数及其梯度(红色曲线为梯度)

前向传播

为了简化数学,我们不讨论向量,而是关注单个神经元,y1

上图清晰地展示了牵涉到的部分:

  • 前一层的三个神经元(扇入

  • 权重(w11、w21、w31

  • 我们想要计算方差的神经元y1

假定xy为独立同分布,我们可以计算y1方差

应用之前简短温习中提到的关于方差的性质:

好了,差不多好了!记住,我们的目标是保持所有层的方差类似。换句话说,我们想要让x的方差和y的方差相等。

对神经元y1而言,这可以通过按下式选取权重方差达成:

推广到隐藏层XY所有连接权重,我们有:

顺便说下,这就是我们从正态分布抽取随机权重所用的方差

如果我们想要使用均匀分布呢?我们只需计算(对称的)上限和下限:

完工了?!还没有……别忘了反向传播,我们同样希望保持所有层的梯度相似(准确地说是梯度的方差)。

反向传播

同样,让我们查看反向传播中的单个神经元x1

上图清晰地展示了牵涉到的部分:

  • 后一层的五个神经元(扇出

  • 权重(w11、w12、w13、w14、w15

  • 我们打算计算梯度方差的神经元x1

我们基本上将做出和前向传播一样的假设,遵循一样的步骤。我们首先计算x1梯度方差

再次使用简短的温习中提到的性质:

同样,为了保持所有层的梯度方差相似,我们选取所需的连接权重方差

好,我们已经取得了不小的进展!扇入的倒数提供了前向传播所需的权重方差,而扇出的倒数提供了反向传播所需的(相同!权重方差

但是……如果扇入扇出的值大不相同,那会怎么样?

调解前向传播和反向传播

无法决定到底是根据扇入还是扇出来计算网络权重方差?没问题,只需取平均数

所以,我们最终得到了GlorotBengio论文中正态分布使用的权重方差的表达式:

至于均匀分布,我们计算相应的上下限:

恭喜!你(重新)发现了Xavier / Glorot初始化方案

不过还有一个细节,你应该从正态分布中抽取权重吗?

截断正态分布

我们希望神经网络的权重齐整地以零为中心分布,不仅如此,我们不希望有任何离散值!所以我们加以截断

截断是什么意思?直接移除任何高于或低于两个标准差的值!所以,如果你使用的标准差是0.1,一个截断正态分布绝对不会有低于-0.2或高于0.2的值

不过,一旦我们截断了正态分布的尾巴,剩余值会有略低的标准差。因此我们需要对此加以补偿。

上图左侧为截断正态分布(绿色)和正态分布(紫色)的对比,右侧为截断正态分布(绿色)和补偿后的方差缩放(粉色)的对比。

还记得之前我提醒你使用Keras 2.2.0以上的版本吗?正是因为Keras 2.2.0之前的版本的Variance Scaling(方差缩放)初始化没有考虑补偿问题。在比较深的模型中,截断正态分布会有随着层数的加深方差缓慢收缩的问题,因此表现可能不如基于均匀分布的初始化。

给我些图形看看吧

非常感谢你在上面涉及很多数学的部分包容我。你的耐心将得到图形作为奖励!

让我们看看Glorot初始化Keras是这么称呼的)表现如何?

正态分布

均匀分布

看起来我们有两个赢家

还记得我们之前的赢家吗?使用标准差为0.1朴素初始化。结果难以置信地相似,对吧?

好吧,实际上我们当初使用的0.1标准差正好是扇入扇出为100时根据Glorot初始化方案计算出的值(只不过我们没有使用截断正态分布)。

所以,这一初始化方案解决了我们碰到的梯度消失爆炸问题……不过,它是否能配合tanh之外的激活函数呢?让我们看看……

ReLU激活函数

Glorot初始化搭配ReLU激活会是什么效果呢?

显然,此路不通!

我们需要一个新的初始化方案。让我们进入Kaiming He等在Delving Deep into Rectifiers(深究整流函数)论文中提出的方案……

He初始化

很幸运,我们在(重新)发现Glorot初始化方案中得到的结论仍然成立。我们只需要进行一项微小的调整……将权重的方差乘以2!真的,就这么简单!

够简单,对吧?不过,为什么

ReLU激活函数及其梯度(红色折线为梯度)

原因相当直接:ReLU一半Z值(负值)变为零,实际上移除了大约一半方差。所以我们需要加倍权重的方差以补偿这一点。

最终的表达式为:

正态分布

均匀分布

注意,上式中我们仅仅使用了扇入,而没有像之前Glorot初始化那样使用扇入和扇出的平均数。这是因为He等发现,仅仅使用扇入或者扇出就足够了。根据扇入计算出的前向传播的权重方差,在通常的网络架构下,反向传播阶段不会导致梯度消失问题;反之亦然。

相应的图形:

正态分布

均匀分布

同样,我们有两个赢家!Z值的分布在所有层都非常相似!至于梯度,和之前tanh/Glorot的组合相比,看起来稍微有点消失的样子……这是否意味着tanh/GlorotReLU/He更好?我们知道并非如此……

不过,为什么梯度看起来没有之前那么好?好吧,再一次,别忘了看下尺度!尽管在反向传播的过程中,梯度的方差出现了下降,它的值离消失差得远(还记得之前我们碰到过的一种梯度消失的情形吗?各层的方差相似,但尺度在0.0000001左右!)

所以,我们不仅需要所有网络层具备相似的方差,同时需要梯度有恰当的尺度尺度也很重要,因为它和学习率一起决定了权重进行更新的过程能有多快。如果梯度过小学习(即权重更新)会极端缓慢

你会问,多小才算过小呢?它取决于权重数量级。所以过小不是一个绝对的测度,而是一个相对的测度。

如果我们计算梯度的方差和相应的权重方差比值,我们可以粗略地比较不同初始化方案和其使用的底层分布学习速度(假定学习率是恒定的)。

所以,现在是比较的时间了……

一决胜负

诚实地说,GlorotHe的对比实际上意味着tanhrelu的对比,我们都知道这一比赛(剧透警告!)的结果:ReLU获胜

不过正态分布和均匀分布哪个更好呢?让我们看下下面的图形:

好吧,实际上我们计算的是标准差的比值,而不是方差的比值,不过两者是等价的。

赢家是……均匀分布!很明显,至少对我们特定的模型和输入而言,相比正态分布,使用均匀分布能产生相对更大的梯度

此外,和期望的一样,相比tanh,使用ReLU能产生相对较大的梯度。在我们的特定例子中,这一点在第一层上并不成立,因为它的扇入只有10(输入的维度)。假设我们使用100维输入,ReLU在那一层也会有相对较大的梯度

同时,尽管ReLU梯度也许看起来有点“消失”的样子,请看看上图每层最右微小的紫色条形……我在图形中塞入了朴素初始化搭配sigmoid激活的结果,以突出真正的梯度消失会是多么糟糕。如果图形仍然不能说服你,看看对应的表格吧:

总结一下,对ReLU激活网络而言,He初始化方案搭配均匀分布是一个相当不错的选择 ;-)

有很多分析选择特定的初始化方案的效果的方式……我们可以尝试不同的网络架构(比如“漏斗”或“沙漏”型的网络),更深的网络,改变标签的分布(以及相应的损失函数)……我尝试了大量组合,He和均匀分布的搭配总是比其他方案要好,由于这篇文章已经很长了,所以我将省略这部分内容。

最后的话

这是一篇很长很长的文章,特别是对权重初始化这样我们认为理所当然的主题而言。不过我觉得,为了真正领会它的重要性,应该循序渐进,并在此过程中遭遇相应的问题,正是这些问题促使了今天使用的初始化方案的开发。

甚至,尽管作为一个从业者,你已经知道初始化你的网络的“正确”组合,我真心希望这篇文章能给你一些洞见,关于初始化过程到底发生了什么,以及更重要的,为什么那个特定组合是“正确”的选择 :-)

如果你觉得这篇文章有用,请给本文点赞。

有任何想法、评论或问题,请留言或在Twitter上联系我(dvgodoy)。

感谢Ludovic Benistant对本文草稿给出的反馈意见。

原文地址:https://towardsdatascience.com/hyper-parameters-in-action-part-ii-weight-initializers-35aee1a28404

: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存