本文是小牛翻译团队成员李垠桥对普林斯顿大学Xiaoliang Dai等人2017年所写NeST: A Neural Network Synthesis Tool Based on a Grow-and-Prune Paradigm论文的解读。
李垠桥同时也是东北大学自然语言处理实验室硕博连读生,入选“小牛人才培养计划”的首批成员。
前言
普林斯顿大学在2017年年末提出了一种自动构建神经网络结构的方法,旨在能够从数据中学习如何自动且高效地设计出一种适合于当前任务的网络结构,本文对论文(NeST: A Neural Network Synthesis Tool Based on a Grow-and-Prune Paradigm)中提出的方法进行了详细的介绍和剖析,希望可以为对该课题感兴趣的朋友提供一些帮助。
众所周知,神经网络的训练离不开海量的数据和优秀的网络结构,随着数据量的增长以及各式各样性能优异的模型结构的提出,神经网络无论在语言处理还是图像识别等领域中性能都获得了骄人的成绩。
为了进一步提高网络的性能,一方面可以通过增加数据量的方式,但更多时候对模型结构的改进也是众多研究人员所关心的重点。那么一种好的网络结构是怎么得来的呢?一般来说是针对我们不同的研究任务所“设计”出来的,比如在机器翻译中引入Attention层或是CNN的结构来具体解决现实中存在的某一类问题。但这样做相对来说还是带有一种系统工程的味道,有些类似于传统的统计机器翻译,我们需要不断的针对现有模型存在的问题来寻找新的特征,不断试错,而这种试错的过程就是对神经网络结构上的一种探索。
我们经常说所谓的“训练模型”,但其实归根结底我们是在训练模型的“参数”,而非站在“结构”的层面去考虑如何进一步对性能进行优化。而去设计结构这件事做起来又仿佛摸着石头过河,看起来尝试的新结构在理应获得很好的性能改善,但得到的实验结果却往往不能一击制胜。过程中的问题主要包括:
1
探索模型结构的时间周期长:我们需要去设计出一种合理化的结构,同时需要大量的时间来通过实验的方式训练参数来验证模型的有效性。通过不断重复这个过程最终才可能找到一种更加优秀且合理的网络结构。由于在实验前并不确定方式方法的有效性,所以这部分的工作一般来说会产生较大的时间代价。
2
设计出的模型结构往往存在冗余:由于设计结构的时候仅仅考虑模型的有效性,没有一种合适的策略去对模型结构中不那么重要的部分进行考量,因此设计出的结构即使能够在性能上取得突破,但一般在结构上依然存在可以精简的部分。
针对以上问题,NeST: A Neural Network Synthesis Tool Based on a Grow-and-Prune Paradigm中提出一种新的作业模式,让网络能够从训练数据中自动学习如何调整,如何设计自己的结构。
整个过程主要包括两个过程、四个状态,从起始的种子结构,依次通过生长阶段和剪枝阶段达到最终的模型结构,转换过程如下图所示。
整个过程从种子结构开始,它并不是凭空而来的,而是根据以往的模型结构所“削减”出一个参数稀疏的模型,从上图中也可以观察到它并非全连接的一个网络。第二个阶段是生长阶段,这个过程通过构建新的连接、增加新的神经元来使得网络结构达到我们所期待的性能。第三阶段是剪枝,在对性能不影响或影响较小的情况下,从网络中删减掉部分连接,使得网络的结构更加紧凑,同时降低模型在存储上的压力以及计算中的消耗。通过上述两个过程最终获得最后生成出的模型结构。
论文作者指出,这种先增长后剪枝的方法灵感来自于人类大脑中神经元的增长过程。下图展示出了论文中整个模型构建过程中神经元连接的数量变化情况。可以看到最初的连接数量相对较少(种子结构),之后通过生长阶段使得连接的数目快速增长到一个相对较多的状态,这时开始进行剪枝,随着剪枝过程的进行,神经元连接的数目又开始不断减小,最终达到有一个平稳的状态(最终结构)。生长阶段和剪枝阶段分别对应着婴儿大脑和成人大脑中神经元的变化情况。人类刚出生的时候,大脑中神经元及其连接的数目相对较少,这时刚出生的婴儿开始逐渐接触身边的事物,有了学习新事物的需求,于是大脑开始主动地进行神经元连接的扩增,使得婴儿有能力去学习身边的新鲜事物。但当神经元的数目达到一定程度的时候,大脑结构已经有足够高的复杂度,足以去应对学习和思考这件事的时候,为了使我们的大脑能够去保持一个低功耗的状态运行,大脑又开始不断地对脑中结构进行简化,去除掉不重要的神经元及连接,并最终达到一个稳定高效的状态。整个过程同作者提出的先生长、后剪枝的过程基本一致,使神经网络结构最终达到一个优秀且紧凑的状态。
作者提出的方法中生长和剪枝这两个过程分别针对我们之前提到的时间周期长和结构中存在冗余这两个问题进行求解,前者通过将网络结构的学习和参数的训练进行了结合,使得结构的设计不再是“盲目试错”,而变成了“有法可依”,大大加速了网络结构设计的速度。后者通过剪枝的策略在保证性能的同时,对冗余部分的连接进行删减,保证网络结构的高效稳定。
接下来我们将详细介绍一下如何通过生长和剪枝的方法对网络结构进行构建。
我们都知道神经网络由神经元和连接组成,因此生长阶段主要包括神经元的增长和连接的构建,分别用红色的节点和线以及棕色的线表示。
首先我们先介绍一下如何向神经网络中增加新的连接(上图棕色线)。我们知道非全连接的网络结构是由许多稀疏矩阵构成的,如下图所示。其中矩阵中有值的部分为相邻两层节点之间的连接(下图矩阵中白色块),而稀疏矩阵中始终为零的位置对应着不存在连接的两个节点(下图矩阵中黑色块)。那么如果要在这样的两个节点之间建立一条新的连接就只需取消对矩阵中对应位置的值固定为零的限制,同时将其通过反向传播算法更新为一个有实际意义的值即可,这样做就相当于在两个节点之间建立起了一条新的连接。
那么具体如何确定要在哪些节点之间建立新的连接呢?作者提出的一种方式是,找到具有强烈关联关系的节点,在它们之间建立连接。所谓的“关联关系”,其实可以理解为一种“欲望”。这个“欲望”指的是对于神经网络本身,强烈地想要将两个节点的连接在一起的欲望。而作为网络本身想要将两个节点连接起来的目的是什么呢?无外乎就是使损失函数的值尽可能地降低。因此我们需要做的就是,找到那些建立起连接后能大幅度降低网络整体损失值的节点,在它们之间建立起新的连接。那么具体来说,我们要如何去衡量在哪些节点之间建立连接的对于损失函数值的下降最有好处呢?毫无疑问就是损失函数对权重的导数了()。经过简单地推导我们可以得到上述损失函数对某两个节点之间的权重求导的公式如下所示。
我们可以通过对两层之间的每两个未连接的节点的这个值进行比较,以确定我们要在哪些节点之间建立起新的连接。
接下来我们介绍一下如何在网络中增加新的节点。首先神经元和连接的增长在本质上有什么不同呢?连接增长的对象是紧挨着的两层节点之间的连接,而神经元增长是指在某一层中增加一个节点,然后连接它的上下层,因此实际上它考察的对象是跨层之间的节点,而非相邻层的节点对。
那么如果我们要在某一层增加一个节点的话,实际上将会改变它的上下层之间连接矩阵的形状,如下图中所展示出的,在原本的参数矩阵某一维度中增加了一组参数。
同样,我们需要考虑的第一个问题就是要在哪一层中增加一个节点,同时将其与前后层的那些节点相连。我们常常说节点的生长过程是我们要在某一层中增加一个节点,同时将其与前后层的某些点进行连接,但实际的逻辑并不是这样。我们其实依旧是为了在两个节点之间建立起新的连接,只不过问题是这两个节点恰好不在相邻的两层中,而是中间隔了一层,因此我们需要在中间层建立一个节点,间接地将它们连接起来。
那么接下来的问题就是,我们要如何考量两个跨层的节点之间的关联程度呢?同理可鉴,我们可以借用连接增长中得到的方式,去考察损失函数对这两个节点之间的连接权重的导数。但是问题来了,这两个节点之间并不存在一条显性的连接,也就是我们不知道要对谁去求导。这里我们可以把问题看得开一点,下图中第三层存在的意义在于什么呢,无外乎就是承接第二层节点的值,把这些值通过一系列变化,进一步传递给第四层,那我们这里不妨就将它看成是一种第二层和第四层之间的直连。当然这是不准确的,也不是一种等价的变换,我们为什么要在神经网络中构建一层一层节点这样的概念,就是因为节点带有连接所不具备的一点优势,非线性变换。但由于这里我们只是想考察节点之间的关联关系,我们便将它近似地看作不存在激活函数的情况,也就是单纯地看成是线性的变换,那么我们就可以把中间这一层省略掉,因为通过层与层之间的直连也能模仿这样的过程。
那么接下来的工作就和连接增长的方式很相近了,我们去考察跨层之间的节点之间的关联程度,具体公式如下。
在神经元增长中还有一个问题需要引起我们的注意,那就是如何初始化我们新增加的附加到矩阵上的权重向量呢?首先要简单说一下为什么同样是在神经网络中增加(或改变)部分权重,在神经元增长这个部分要格外提出初始化这个问题。我们可以参考下面的公式,它是最普通的反向传播算法的公式,我们可以使用它来对新加入的权重进行更新。如果我们简单地将新加入的权重初始化成零的话,当在连接增长的情况下,我们能够求得新增连接的权重梯度,同时进一步对原本是零的权重值进行更新。但在神经元增长的问题里,由于新加入的节点同前一层的连接只有新加入的一条(或若干条),但这些值均为零,因此梯度值为零,无法有效地使用反向传播的方式进行权重的更新,因此需要引入一种合适的初始化方式来解决这个问题。当然你可能会觉得,那我不将新增的连接权重初始化成零,比如说随机初始化就没有这个问题了,的确,这里只是通过零的情况给大家提供一种相对简单的理解方式,但作者希望提出一种更加优秀的初始化方式,使得网络收敛速度相对随机的方式更快一些。
那么要如何在神经元增长问题中初始化新增加的连接权重呢?答案是模仿我们之前提出的虚拟连接。为什么要模仿虚拟连接呢?首先虚拟连接的好处在于它跨过了一层,将前后两层的节点直接联系了起来,使得我们可以去得到它所谓的权重梯度。这样做是一种对节点连接的近似,但是重点是它可以计算虚拟连接上的梯度。有了梯度,我们就知道了虚拟连接变成什么值会让网络的损失值降低,这一点和我们希望通过增加节点的目的是相同的。那么如何模仿呢?如果虚拟连接和节点连接这两种方式在通过反向传播的方式调整了权重参数后,下一层的输入是相同的,那么我们就可以将这二者的效果看成是等价的。
虚拟连接和真实节点连接的具体推导公式如下,原理很简单,这里我们不进行赘述。
最终让虚拟连接和节点连接的相等,同时假设新增节点的输入层与输出层新增的权重变化情况是相同的(即),就可以得到新增的权重向量的变化情况(如下式所示),用它来对其进行初始化会使得系统更容易收敛。
为了计算方便,在我们计算如何初始化新增的权重向量的时候,是将带着绝对值的相等作为判断条件,因此最后的结果可以得到和变化的绝对值大小。但是如何确定这两个变化值的正负情况呢?我们要注意我们这样推导的初衷在于模仿虚拟连接,因此我们要保证和整体的方向和虚拟连接中梯度下降的方向保持一致。因此这里我们需要根据的正负来确定和的符号,也就是说当为正时,和必须保持同号,当为负时,和必须保持异号。
还有一个要注意的点是,由于我们要将新增的权重向量加到原本的权重矩阵当中,因此需要尽可能地保证加进去的参数和原本的参数绝对值大小处于同一量级,以免过大或过小对模型影响的程度不稳定。于是在论文中对初始化后的权重进行了一下缩放,确保和矩阵整体数值大小相对和谐,具体公式如下。
以上就是模型的生长阶段的全部过程,接下来介绍一下如何对模型进行剪枝,以删除其中存在的冗余。
剪枝的思想相对模型增长相对来说就简单些了,它的思想在于删除网络中没有那么重要的连接及节点,同时每删掉若干个后再对网络重新进行训练,避免错误累计,使得最终剪枝对系统性能影响不大。而既然剪枝的出发点在于删掉那些对模型影响不大的连接或节点,那么最朴素的思想就是对每相邻两层之间的连接绝对值大小进行排序,删除其中较小的部分,这样做使得网络输出的影响没有那么剧烈,达到我们希望的目的。
在介绍完算法中生长和剪枝阶段的主要方式之后,我们再简单回顾一下整个算法的流程。首先我们开始于种子结构,这个结构不是凭空而来的,而是根据相应任务所得到的经验性模型的“删减版”(权重参数矩阵稀疏)。之后在生长阶段,我们会循环往复地想模型中增加新的神经元及连接,同时设置一个模型规模的最大值以及精确度作为这个阶段结束的停止条件(模型过大或精度达到我们的要求时停止)。之后进入剪枝阶段,同样也是不断地对模型进行剪枝,但精度到达一个我们不可接受的点的时候停止该过程,最终得到我们想要的模型。
论文中最后的实验结果如下,我们可以看到在MNIST手写体识别的任务中,相对基线模型,通过本文提出的NeST方法所构建出的模型结构错误率由原本的1.60%减低到1.29%,同时模型大小和运算消耗均得到大幅度降低,如下图所示。
此外在实验过程中可以看到几个有趣的点,在生长阶段,我们可以看出随着种子结构的变大,生长后的模型大小也更大,但与此同时达到我们所设定的某个模型精度所需要的时间也更少。另一方面,我们反过来看,随着种子结构的逐渐变小,生长后的模型结构并不是会无止境地减小,而是有一个最小值的。原因很简单,因为我们希望模型完成的任务复杂度是固定的,太小的模型很可能根本不具备那么强的表达能力去完成相应的任务。
下图展示出的是论文中的剪枝阶段,我们可以看到剪枝前模型越大,那么剪枝的比率相对来说也会更高一些,同时剪枝前的模型越大,经过剪枝后的模型大小也要相对于小模型剪枝后的结果要大一些。原因在于因为我是用模型的精确度来约束什么时候剪枝结束,因此,大的模型本身参数量就多,因此一般来说剪完也比小模型剪完要相对较大。
最后,对这篇论文进行一个简单的总结,首先这篇论文提出的网络构建方法的确给我们提供了一个很清晰的思路,让网络能够通过对数据的分析来逐渐学习如何设计网络结构,但它却依旧依赖于所谓的“种子结构”,也就是依然不能完全摆脱人工设计的网络架构。那么我们要如何看待这篇论文提出的NeST方法呢?一方面我们可以将其看作是一种对某种模型结构性能极限探索的工具,比如说我们可以通过先生长再剪枝的方式来判断模型中的哪部分结构是真正起到核心作用的。另一方面,我们也可以把NeST方法看作是一种更好的模型裁剪手段,通过实验结果我们也可以看出,这种先增长后剪裁的方式得到的模型,无论在性能还是模型大小上都更具优势,因此它也不失为一种模型裁剪的好方法。
此外,论文中提出的这种根据数据集自动构建神经网络的方式,为网络结构的学习提供了一个良好的范本,但其中进行探讨和分析的对象却仍然仅限于比较基础的定长序列,主要针对前馈网络的结构和卷积网络进行研究。而在机器翻译等任务中,我们要处理的对象通常为许多长度不一的句子,因此如何有效地利用NeST这种网络构建的方法对网络结构进行有效地学习仍然有待我们进一步思考和探索,尚且不能简单地将其直接套用到机器翻译的任务中来。
基于37年的机器翻译技术积累,小牛翻译引擎致力于为用户提供最专业的机器翻译解决方案,目前支持以中文为核心与其他43种语言互译,全面支持“维蒙藏哈朝彝壮”七大少数民族语言。2016年获得国内自然语言处理领域最高科学技术奖——钱伟长中文信息处理科学技术奖一等奖,成为首次荣获该奖的机器翻译研发团队。
小牛翻译∣专注机器翻译
领取专属 10元无门槛券
私享最新 技术干货