在阅读近期的CVPR2019时,看到一篇比较亮眼的图像分割论文。来自斯坦福 Li Fei-Fei组(Auto-deeplab),关于利用NAS策略进行图像分割,达到了较优的水平,仅仅比deeplabv3+少1.3%,且只用了3张P100 GPU。收集一些关于NAS的资料,做一个神经网络架构搜索综述,在借鉴部分给出相应的链接以及引用,侵删。
神经网络结构搜索(Neural Architecture Search,NAS)是自动机器学习(Auto-ML)领域热点之一,通过设计经济高效的搜索方法,自动获取泛化能力强,硬件要求友好的神经网络,大量的解放研究员的创造力。在现今深度学习的浪潮中,“炼丹师”作为深度学习工作者自嘲的称号使得NAS注定将成为新的研究热点。
人工神经网络结构设计vs自动神经网络结构搜索
经典的NAS方法中,主要包含以下三个方面:
网络架构和超参数优化的问题,有以下的特点:
NAS是一个确定环境中的完全延迟奖励任务。在下图DAG中,方框表示节点,具体的物理意义是feature map。不同颜色的箭头表示不同的operations。s表示当前网络结构状态,a表示每一步的动作,r表示得分。只有在网络结构最终确定后,agent才能获得一个非零得分acc
上图展示了一个NAS的马尔科夫决策过程(MDP)的完整过程。可以看到的是,在每一个状态(state)中,一旦agent产生了动作,网络结构状态的改变是确定的。而在一个网络被完全搭建好并训练及测试之前,agent的每一个动作都不能获得直接的得分奖励。agent只会在整一条动作序列(trajectory)结束之后,获得一个得分。
简单总结一下,就是,NAS是一个确定环境中的完全延迟奖励的任务。(A task with fully delayed reward in a deterministic environment.)
搜索空间定义了优化问题的变量,网络结构和超参数的变量定义有所不同,不同的变量规模对应算法的难度来说也不尽相同。在早起的一些工作中,以遗传算法为代表的进化算法对神经网络的超参和权重进行优化,因为当时的神经网络尚处浅层网络,可直接对其进行优化。而深度学习模型一方面有着复杂的网络结构,另一方面权重参数通常以百万计,进化算法无法企及。
目前常见的一种网络架构是链状结构,如下图:
这种结构相当于一个 N 层的序列,每一层有几种可选的算子,比如卷积、池化等,每种算子包括一些超参数,比如卷积尺寸、卷积步长等。最近的一些工作受启发于一些人工设计的网络架构,研究带有多分支的网络,如下图:
很多的深层 RNN 会有类似的结构,很多的网络结构虽然很深,但会有许多重复 cell,将 cell 抽象出来之后,复杂的结构也会变得简单,一方面可以减少优化变量数目,另一方面相同的 cell 在不同任务之间进行迁移,如下图。
常见的搜索方法包括:随机搜索、贝叶斯优化、进化算法、强化学习、基于梯度的算法。
强化学习
开创性的工作主要是2016年由MIT发表的《Designing Neural Network Architectures using Reinforcement Learning》和Google发表的《Neural Architecture Search with Reinforcement Learning》两篇文章。前者提出MetaQNN,它将网络架构搜索建模成马尔可夫决策过程,使用RL方法(具体地,Q-learning算法)来产生CNN架构。对于CNN的每一层,学习体会选取层的类型和相应参数。生成网络结构后训练后得到的评估精度作为回报。这个回报用以参于Q-learning训练。作者在SVHN、CIFAR-10和MNIST三个数据集上进行了实验。用了10个GPU花费8-10天时间,基本可以击败同『重量级』的网络。后者采用RNN网络作为控制器来采样生成描述网络结构的字符串,该结构会用于训练并得到评估的准确率,然后使用了REINFORCE算法(早期的RL方法,在他们后面的工作中又使用了比较新的更加sample efficient的PPO算法)学习控制器的参数,使之能产生更高准确率的网络结构。它动用了800个GPU,最终在CIFAR-10数据集上击败了具有类似网络架构的人工设计模型,在PTB数据集上达到了新的SOTA水平,并且还找到了比广泛使用的LSTM更优的结构。
在 NAS 任务中,将架构的生成看成是一个 agent 在选择 action,reward 是通过一个测试集上的效果预测函数来获得(这个函数类似于工程优化问题中的 surrogate model,即代理模型)。这类工作整体的框架都是基于此,不同的点在于策略表示和优化算法。
一个工作是,用 RNN 来表示策略函数,初始化时先用策略梯度算法赋初值,然后用 PPO 来进行优化。另一个工作是,用简单的 Q-learning 算法来训练策略函数,序列地进行动作选择,即选择 layer 的类型和相关的超参数。
因为在 NAS 任务中,agent 与环境没有交互,可以降阶为无状态的多臂老虎机(MAB)问题。 这里的几个工作都是近两三年的新工作,后面会对这些 paper 进行专门解读。
进化算法
在Google的论文《Large-Scale Evolution of Image Classifiers》中,进化算法被引入来解决NAS问题,并被证明在CIFAR-10和CIFAR-100两个数据集上能从一个简单的初始条件开始达到高的精度。首先,网络结构会进行编码,称为DNA。演进过程中会维扩护网络模型的集合,这些网络模型的fitness通过它们在验证集上的准确率给出。在进行过程中,会随机选取两个模型 ,差的那个直接被干掉(淘汰),好的那个会成为父节点(这种方式为tournament selection)。子节点经过变异(就是在一些预定的网络结构变更操作中随机选取)形成子结点。子结点经过训练和验证过放入集合。该作者在后续论文《Regularized Evolution for Image Classifier Architecture Search》中,提出了tournament selection的变体aging evolution,让进化中的选择倾向于比较『年轻』的模型,它可以帮助更好地进行探索。经搜索出的最优网络结构称为AmoebaNet(源码链接)。另外作者对强化学习,进化算法和随机搜索作了比较,发现强化学习和进化算法从准确率上来说表现很好。与强化学习相比进化算法搜索得更快(尤其是早期),且能得到更小的模型。随机搜索在学习到的网络准确率上会次于前面两者,但差距不是那么大(尤其是小数据集上)。
进化算法是一大类算法,大概的框架也基本类似,先随机生成一个种群(N 组解),开始循环以下几个步骤:选择、交叉、变异,直到满足最终条件。最近几年流行一种基于概率模型的进化算法 EDA (Estimation Distribution of Algorithm),基本的思路类似遗传算法,不同的是没有交叉、变异的环节,而是通过 learning 得到一个概率模型,由概率模型来 sample 下一步的种群。
用进化算法对神经网络超参数进行优化是一种很古老、很经典的解决方案,90 年代的学者用进化算法同时优化网络结构参数和各层之间的权重,因为当时的网络规模非常小,所以还能解决,但后续深度学习模型网络规模都非常大,无法直接优化。
进化算法是一种无梯度的优化算法(Derivative Free Optimization Algorithm),优点是可能会得到全局最优解,缺点是效率相对较低,近两年几家高科技企业做 NAS 时都在用进化算法优化网络结构,同时用基于梯度的方法(BP)来优化权值。在 NAS 任务中,进化算法的交叉算子和任务结合比较紧,被定义为一些类似添加、删除层的操作,而非简单的更改某一位编码。
用进化算法解决 NAS 问题,不同的工作可能聚焦在不同的过程中,比如如何 sample 种群,如何 update 种群,如何生成子代种群等。这些工作将会被在后面的文章中进行解读。
贝叶斯优化
贝叶斯优化(Bayesian Optimization)是超参数优化问题的常用手段,尤其是针对一些低维的问题,基于高斯过程(Gaussian Processes)和核方法(kernel trick)。对于高维优化问题,一些工作融合了树模型或者随机森林来解决,取得了不错的效果。
除了常见的三大类方法,一些工作也在研究分层优化的思路,比如将进化算法和基于模型的序列优化方法融合起来,取各种方法的优势。Real 在 2018 年的一个工作对比了强化学习、进化算法和随机搜索三类方法,前两种的效果会更好一些。
基于梯度的方法(Gradient-based method):这是比较新的一类方法。前面提到的基于强化学习和进化算法的方法本质上都还是在离散空间中搜索,它们将目标函数看作黑盒。我们知道,如果搜索空间连续,目标函数可微,那基于梯度信息可以更有效地搜索。CMU和Google的学者在《DARTS: Differentiable Architecture Search》一文中提出DARTS方法。一个要搜索最优结构的cell,可以看作是包含N个有序结点的有向无环图。结点代表隐式表征(例如特征图),连接结点的的有向边代表算子操作。DARTS方法中最关键的trick是将候选操作使用softmax函数进行混合。这样就将搜索空间变成了连续空间,目标函数成为了可微函数。这样就可以用基于梯度的优化方法找寻最优结构了。搜索结束后,这些混合的操作会被权重最大的操作替代,形成最终的结果网络。另外,中科大和微软发表的论文《Neural Architecture Optimization》中提出另一种基于梯度的方法。它的做法是先将网络结构做嵌入(embedding)到一个连续的空间,这个空间中的每一个点对应一个网络结构。在这个空间上可以定义准确率的预测函数。以它为目标函数进行基于梯度的优化,找到更优网络结构的嵌入表征。优化完成后,再将这个嵌入表征映射回网络结构。这类方法的优点之一就是搜索效率高,对于CIFAR-10和PTB,结合一些像权重共享这样的加速手段,消耗可以少于1 GPU/天。
上面提到,由于NAS中涉及的搜索空间巨大,而且其性能评估往往得涉及模型的训练,导致消耗的资源很大。像前面提到的基于强化学习和进化算法的方法,对于CIFAR这样不算大的数据集,基本都是用了上千GPU/天,家里没矿的或是小公司可能连研究的门槛都没到,可以说基本还没法平民化。因此,后面的一大批论文就是和这个问题作斗争。其中比较典型的加速方法有几类:
以上主要针对NAS本身的改进,且主要实验限于图像分类任务和自然语言处理,且大多只关注模型准确率。很自然的,大家就将NAS往其它的任务上应用,或者将更多因素纳入目标考虑。比如下面两项工作:
NAS已在一些基本任务及数据集上证明能超越人类手工设计,那在其它深度学习相关的超参数上是否也能使用类似的思想让机器自动学习,从而得到比人工设计更好的参数,并免除人肉调参的痛苦呢。下面列举了几个这方面比较有趣的尝试。
优化器:相对网络结构来说,优化器的迭代可以说是比较慢的,但每次重要的演进又很容易引人关注,因为这个太通用了。从最基本的SGD到Adagrad, Adadelta, RMSProp,Adam等更加精巧的更新方式,很多其实是加入了一些启发(如物理中的momentum概念),还是属于手工打造,实验证明。论文《Neural Optimizer Search with Reinforcement Learning》将使用在NAS上的方法拓展到了优化器(更准确地,更新公式)的优化上。与其它类似工作相比其优点之一是它输出的是更新公式,因此在不同模型和任务间具有更好的迁移能力。首先将更新规则用字符串描述,其描述了该更新公式中所使用的操作数(像梯度及其幂,和它们的指数滑动平均、噪声、Adam/RMSProp或一些常数等),应用在其上的unary函数(取负、自然底数、绝对值取对数、clip等),以及操作数之间的binary函数(加减乘除等)。然后采用NAS中类似的基于RNN的控制器,之后用验证集精度为回报来采用强化学习训练控制器。作者实验中找到了两个新的优化器 - PowerSign和AddSign,并被证明在实验数据集上强于现在常见的优化器。
模型压缩:这几年,模型压缩可谓是深度学习中最为火热的分支之一。该方向对于落地到移动端上尤其重要。在AutoML的浪潮下,这项工作也有了新的拓展。MIT,西安交大和Google的论文《AMC: AutoML for Model Compression and Acceleration on Mobile Devices》主要针对模型压缩中的重要方法之一 - 剪枝(Pruning)。业界普遍认为虽然模型训练时需要复杂的结构,但训练好的模型一般有比较高的冗余度,因此可以进行裁剪,且只降低很少精度,甚至可能提高精度(由于剪枝能起到正则化效果,从而提高模型的泛化能力)。但是,剪枝策略中的参数选择是件很tricky的事。拿稀疏率来说,由于每层可能都有不同的冗余程度,因此有各自不同的最优稀疏率。虽然有不少启发式的策略,但还是需要人肉试验看效果。这篇文章提出AMC(AutoML for Model Compression)方法,引入强化学习(具体地,DDPG算法)来学习最优的参数,并且通过设计不同的回报函数可以让最后得到的模型满足不同需要(如高压缩率,或是保证精度)。实验表明,在ImageNet数据集VGG-16模型上,在计算量减少到1/4的情况下准确率比人工调参下高2.7%;另外MobileNet模型可以在准确率只掉0.1%的前提下在Android手机和Titan XP GPU上分别达到1.81和1.43倍的加速。
数据增强:AutoML的意义在于把之前启发式人工设计的东西用机器搜索来替代。而深度学习尤其是视觉任务中,有一项容易被忽视但又对结果至关重要的就是数据增强,它被认为可以很大程度上在已有数据集条件下增强模型的泛化能力。另外,数据增强方法的挑战之一是它不是完全通用的,如某一特定数据集上最优的数据增强方法可能并不适用于另一数据集。这就意味着对于特定任务,我们需要找到最适合的数据增强手段。论文《AutoAugment: Learning Augmentation Policies from Data》正是做了这方面的探索,首先定义搜索空间:一个数据增强策略包含五个子策略,每个子策略包含两个图像操作,每个图像操作包含两个超参数:一个是应用该操作的概念,另一个是操作相关应用程度。考虑的操作包含shear, translate, rotate等16种。这样就把该问题很好地转化为最优参数搜索问题了。然后基本可以沿用NAS中的方法,使用一个基于RNN的控制器来给出数据增强策略,然后将应用该数据增强策略下的模型精度作为回报,使用强化学习(具体地,PPO算法)训练该控制器。作者实验表明,该方法可以在CIFAR-10, CIFAR-100, SVHN和ImageNet数据集上达到了SOTA水平。
评价预估类似于工程优化中的代理模型(surrogate model),因为深度学习模型的效果非常依赖于训练数据的规模,大规模数据上的模型训练会非常耗时,对优化结果的评价将会非常耗时,所以需要一些手段去做近似的评估。
一种思路是用一些低保真的训练集来训练模型,低保真在实际应用可以有多种表达,比如训练更少的次数,用原始训练数据的一部分,低分辨率的图片,每一层用更少的滤波器等。用这种低保真的训练集来测试优化算法会大大降低计算时间,但也存在一定的 bias,不过选择最优的架构并不需要绝对数值,只需要有相对值就可以进行排序选优了。
另一种主流思路是借鉴于工程优化中的代理模型,在很多工程优化问题中,每一次优化得到的结果需要经过实验或者高保真仿真(有限元分析)进行评价,实验和仿真的时间非常久,不可能无限制地进行评价尝试,学者们提出了一种叫做代理模型的回归模型,用观测到的点进行插值预测,这类方法中最重要的是在大搜索空间中如何选择尽量少的点预测出最优结果的位置。
第三种主流思路是参数级别的迁移,用之前已经训练好的模型权重参数对target问题进行赋值,从一个高起点的初值开始寻优将会大大地提高效率。在这类问题中,积累了大量的历史寻优数据,对新问题的寻优将会起到很大的帮助,用迁移学习进行求解,是一个很不错的思路。
另一种比较有意思的思路叫做单次(One-Shot)架构搜索,这种方法将所有架构视作一个 one-shot 模型(超图)的子图,子图之间通过超图的边来共享权重。
[1] 神经网络架构搜索(Neural Architecture Search)杂谈
[2] 神经网络架构搜索(NAS)综述
[3] 一文详解随机神经网络结构搜索 (SNAS)