介绍
首先这篇综述是讲AutoML的,不单单是NAS,但是因为NAS是AutoML中最最重要的一部分,所以主要篇章还是用来讲NAS了。据作者所说,应该是第一篇完整讲述AutoML整个流程的综述。
首先,本文将AutoML划分成了如下几个流程:
先是数据准备,然后是特征工程,接着是模型生成,最后就是模型评估了。其中模型生成又可以分为搜索空间和优化方法,搜索空间有传统的ML模型或者DL模型,优化方法又分为超参数优化和结构优化。NAS的话主要就涉及到DL模型的搜索空间定义、结构优化和模型评估策略这三块。
因为我主要关注NAS这块,所以其他部分就只简单介绍一下,不做过多解读。
数据准备
看上面这个图应该很清楚了,数据准备主要分为数据收集、数据清洗和数据增强三个部分。
数据收集
有开源的就去下开源的,没开源的就去互联网上爬,要是什么都没有呢,那就通过GAN之类的技术来生成伪数据,有总比没有好嘛。
数据清洗
就是清洗数据中的噪声、脏数据,这一过程可能需要一些知识去判断什么是噪声。还有一个研究主题就是如何清洗每天更新的源源不断的新数据。
数据增强
数据增强某种程度上也可以被视为数据收集的一种工具,因为效果都是一样的,增加了新数据。但是它的目的有所不同,主要是为了防止模型过拟合。上图针对不同数据有很多增强方法,这里就不介绍了。
特征工程
有句话叫:数据和特征决定了机器学习的上界,而模型和算法只是为了去近似这个上界。主要可以分成三块,特征选择、特征构建和特征提取。这里也不多介绍了,因为在DL里特征工程用得很少,DL模型可以自己从数据中学出特征,很少需要自己手动构造特征了。
模型生成
从这块开始进入到了NAS的领域。之前说了,搜索空间分为ML和DL两块,本文只关注DL,而优化方法又分为超参优化和网络架构优化,本文也主要只关注网络架构优化,因为超参优化是挑选出最优网络架构之后的事情了,不过也有工作将NAS用在超参优化上的,这个就不在讨论范围内了。
上面两张图是NAS的一般流程:
- 首先针对不同的任务定义一个搜索空间,这个搜索空间就决定了你搜出来的网络架构可能长什么样子,也决定了你搜出来的架构可能性有多少,当然是越大越好,但是带来的后果就是搜索速度太慢。
- 然后在这个搜索空间里进行搜索,采样出一个比较好的模型架构,这里方法就非常多了,最简单的就是随机搜索,随机采样一个网络架构。
- 最后就是在训练集上评估你采样出的架构效果,反馈给架构优化,让它优化,然后继续采样,循环下去。评估方法也有很多,最简单的就是像正常训练模型那样完整训练一遍,得到效果,但是这样太慢了,因此需要其他方法来加速训练或者估计效果。
搜索空间
神经网络可以看作是一个DAG,而如何定义这个DAG,其实你可以用生成图的方式做加法生成它,也可以做减法,从大图中抽取出子图等等,有很多方法。
定义搜索空间需要人类知识,这一步目前还不够Auto,定义的好,生成出来的架构才可能好。而有些工作发现只要你搜索空间定义的足够好,随机搜索都能达到和各种架构优化方法相似的效果,那么NAS将变得毫无意义,所以这一块还是挺玄学的。
整体结构搜索
就是按照DAG的拓扑序,依次生成出模型架构出来。一般来说,用一个RNN来生成,每生成一个node,都要预测出它的输入是哪些node(残差)、作用在它上面的op有哪些。
但是这种方法太慢了,搜索的复杂度是指数级别的,因此在最初的几篇RL论文里,都用了几百个GPU训练了几十天才搜出来,穷苦人家可搜不起。
cell搜索
这种方式也是借鉴了人类设计神经网络的经验,像ResNet系列都是将一个个cell层层堆叠得到的,因此如果只搜一个cell,然后将相同的cell堆叠起来岂不是大大减小了搜索空间。后面的很多工作都是基于cell来搜索的,比如NASNet。
在NASNet中,cell被分成了两种,一种是normal cell,它的输入输出维度保持相同,另一种是reduction cell,它的结构和normal cell相似,但是输出的宽度和高度减半,通道数加倍。
最后搜索出最优cell之后,根据需要堆叠不同层数的cell就行了,这个层数也是人为定义的。但是这里就会存在一个训练和评估不一致的问题,一般来说,在搜索的时候,为了减小显存占用,会堆叠比较少的层数去评估。但是在得到最优cell之后,用来retrain时会堆叠比较多的层数,这里就不一定是最优解了。也有工作做这方面的优化,比如P-DARTS,在搜索阶段逐渐增加堆叠的层数。
分层搜索
当然搜索cell也是存在问题的,忽视了整体结构的优化,而且每一层的cell相同也不一定最好啊。因此后来的工作又提出了分层搜索的方法。
比如Auto-deeplab在搜索cell的同时,还搜索了不同层的分辨率,下一层的分辨率可以是一半、不变或两倍,这一步限制一是为了减小搜索空间,二是为了增加稳定性,防止分辨率变化太大。
再如HierNAS,按照层次结构来搜索网络架构,第一层是一些原子操作,第二层用这些原子操作生成一些比较小的网络,第三层用第二层的小网络再搭建出一个更大的网络,依次下去。
再如progressive NAS,为了减小一个cell里面的搜索空间大小,从一个cell里面只有一个block开始搜索,每次挑出top-k个cell,在基础上衍生出两个block,依次下去。评估性能用的是代理模型直接预测,不需要真的训练一遍。
再如MnasNet,它将整个网络分为了若干个cell,每个cell串行了若干个block,每个cell的block数量可能不同,而单个cell里面的block结构是相同的,这样就考虑到了整体的网络搜索空间。和堆叠cell不同的是,每个block的结构比较简单,不然的话整体上搜索复杂度还是太大了。当然这篇主要还是为了做移动端部署,因此做了多目标NAS,将延时也考虑到了目标函数中去。
之前的方法还存在一个问题,就是基本都是在小数据集上做的搜索评估,最后将最优结构运用到大数据集上,这就存在不一致性。因此例如ProxylessNAS就直接在大数据集上搜索评估,为了减小显存消耗,采用BinaryConnect,每次只激活两个结点之间的一条边。