December 12, 2019
by Frank
推荐一篇 survey(虽然到处都在说这个,但我还是要推荐一下)
推荐一篇 survey(虽然到处都在说这个,但我还是要推荐一下)
Neural Architecture Search: A Survey
大致按照时间线来,内容分为这么几块:大力出奇迹,平民化,落地
1,大力出奇迹
被人们所熟知的第一篇 NAS 工作应该是 Google 的这篇NEURAL ARCHITECTURE SEARCH WITH REINFORCEMENT LEARNING[ICLR'17],充分展现了 Google 的实力和财力(划掉)。思路也是简单明了,以前每一层的 filter 数量大小等等都需要人为来定,那就可以做成一个优化问题列几个选项让它自己选个最好的,这样的选择组合起来就成了编码某个网络结构的 token。为了让其更加灵活支持变长 token,使用 RNN 来作为这里的 controller,然后用 policy gradient 来最大化 controller 采样网络的期望 reward,也就是 validation accuracy
后来这帮大佬可能觉得跑个 cifar10 太 naive 了,应该整个 ImageNet,但是像之前这么搞直接在 ImageNet 上搜肯定是跑不动的,别说 800 张卡,8000 张都搞不定。
于是 Google 又出了一篇Learning Transferable Architectures for Scalable Image Recognition[CVPR'18]。那我不搜整个结构,搜个 cell 然后堆起来就行了,反正 VGG/Inception/ResNet 也是这么干的,于是沿用了之前的思路,继续用 RNN 和 policy gradient 在新的搜索空间中寻找最佳的结构,在 cifar 上搜 cell 然后堆起来用到 ImageNet 上。搜索目标只包括两种 cell,一种是 normal cell,另一种 reduction cell 用于 downsample,每个 cell 里面包括一些 block,新的搜索空间包括选择这些 block 使用什么 op,用什么作为输入等。之后很多工作都沿用了 NASNet Search Space 这个套路。
之后大佬们可能觉得现在的 token 都定长了,或许 RNN+policy gradient 的优化方式可以换成一些其他的算法(也可能是觉得强化学习调参太 tm 蛋疼了),于是 Google 又出来一篇Regularized Evolution for Image Classifier Architecture Search[AAAI'19],搜索空间沿用上面的 NASNet Search Space,只是将优化算法换成了 regularized evolution(具体算法还是看 paper 吧...写出来感觉内容太多了(其实就是懒)),搜到的结构叫做 AmoebaNet。实验表明确实 evolution 更加好使,收敛快,效果好,调参还没那么蛋疼。
AmoebaNet 这种方法用 450 块 gpu 跑了 7 天,依旧劝退。。
后来 Google 自己也觉得之前的方法太花时间了,于是又搞了个Progressive Neural Architecture Search[ECCV'18],主要目标就是做加速。将搜索空间减小并且用预测函数来预测网络精度,最后时间缩短到大概 225 个 gpu-day,相比 AmoebaNet 少了十几倍,然而对于普通玩家还是在劝退。。。
2,平民化
像上面这种大力出奇迹的玩法平民玩家基本玩不起,但是计算量的问题摆在这里,自然就有一些解决方案来加速这个过程。
比较有代表性的就是 weight sharing 加速 validation 的Efficient Neural Architecture Search via Parameter Sharing[ICML'18](咦,还是 Google 的 Quoc V. Le 他们),大概思路就是将 NAS 的采样过程变成在一个 DAG 里面采样子图的过程,采样到的子图里面的操作(卷积等)是参数共享的。与之前的方法主要差别就在于 ENAS 中子图的参数从 DAG 继承而来而不是重新初始化,不需要 train-from-scratch 即可以验证子图的精度,极大的加速了 NAS 的过程。
为了评估采样到的子图在数据集上的表现,DAG 的参数(weight 等)是需要优化的,除此之外为了找到最好的子图,采样器(这里使用的 RNN)也是需要优化的。ENAS 采用的是交替优化 DAG 中的参数和采样器中的参数。DAG 参数的优化是通过采样一个子图,然后 forward-backward 计算对应操作的梯度,再将梯度应用到 DAG 上对应的操作通过梯度下降更新参数。采样器 RNN 的更新采用了之前 policy gradient 的优化方式。
ENAS 提出了两种模式(这里只介绍 CNN),一种是搜整个网络结构,一种是搜个 cell 然后按照之前的方式堆起来,在搜索 cell 的时候只需要一张卡跑半天就能跑完。不过最近 ICLR'20 的投稿中对于 weight sharing 有很多不同的声音,有兴趣的可以去openreview看一看。
还有一个很快就能跑完的 NAS 工作是用可微分的方式进行搜索的DARTS: Differentiable Architecture Search[ICLR'19],在今年被各种魔改(我猜很可能是因为开源了 pytorch 的代码,然后代码写得很漂亮改起来也比较容易)。DARTS 和 ENAS 很像,也是从 DAG 中找子图,并且同样采用了 weight sharing,主要的区别在于搜索空间和搜索算法上。搜索空间比较类似 NASNet search space,搜索算法则是采用了可微分的方式。
DARTS 也是搜 cell 然后按照一定的模式堆起来,在搜索算法上与之前的方法最大的区别在于 DARTS 选择某个操作的时候并不是像之前按照 RNN 的输出概率进行采样,而是把所有操作都按照权重(不是直接加权,先将权重 softmax 归一化)加起来,那这样权重就在计算图里面了,在计算验证集 loss 之后就可以 backward 计算权重的梯度,直接通过梯度下降来优化权重。搜索的过程也就是优化权重的过程,最后保留权重最大的操作就是最后搜到的结构。
权重的优化和 DAG 里面 weight 的优化类似于 ENAS,也是交替进行的(在训练集上优化 weight,在验证集优化权重),不过 DARTS 是整个 DAG 进行 forward-backward(这样的缺点在于内存开销会比较大)而不是像 ENAS 一样先采样子图。
DARTS 搜索一次只需要一张 1080ti 跑一天即可,对于平民玩家完全没压力 hhhhh
上面这两项工作让很多只有几张显卡的平民玩家也能玩得起 NAS。
3,落地
上面所介绍的 NAS 工作很少有人工设计网络的影子,基本都是重新设计了新的搜索空间。从实验结果上来 NAS 搜到的网络确实能取得很好的效果,但并不一定适合实际部署(比如 DARTS 能在很小的参数量下达到很高的精度,但是实际 forward 其实很慢)。既然之前已经有了很多优秀的人工设计的网络结构,NAS 可以通过引入这些先验知识来加速或者取得更好的实际部署性能。
先举个最直观的例子,EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks[ICML'19]简单粗暴,既然 MobileNet 在同样精度下速度快,那我把它拿来搞大一点,同样的速度下精度会不会高一点?答案是肯定的
问题在于怎么放大这个网络,单独加深/加宽/加大分辨率效果一般般,EfficientNet 搜索了宽度/深度/分辨率之间的相对缩放因子,将他们按照一定的比例放大,事实证明这种方式(我觉得这应该也算是 NAS)虽然简单但是有效。
还有一个魔改 MobileNetV2 的工作出自 MIT Song Han 组,ProxylessNAS: Direct Neural Architecture Search on Target Task and Hardware[ICLR'19],这篇工作的 point 不在于魔改 MobileNetV2(kernel size,expansion ratio 等),而是在于 proxyless 的理念。想要某个数据集在某硬件上的结果就直接在对应的数据集和硬件上进行搜索,而不是像之前的工作先在 cifar10 搜然后 transfer 到 ImageNet 等大数据集上,并且在目标函数上加入硬件 latency 的损失项作为多目标 NAS,直接面向部署的硬件。
另一个系列的工作也是出自 Google,MnasNet: Platform-Aware Neural Architecture Search for Mobile[CVPR'19]用来魔改 MobileNetV2 里面的 layer 数/卷积操作/加 attention 等等,然后用之前同样的 RNN+policy gradient 的方式来优化
除此之外,NetAdapt: Platform-Aware Neural Network Adaptation for Mobile Applications[ECCV'18]针对特定硬件对已有的网络做压缩,相当于对网络在硬件上做一个结构上的 fine-tune。
Google 后来结合了上面这两项工作,推出了Searching for MobileNetV3[ICCV'19],把 MnasNet 魔改的 MobileNetV2 再用 NetAdapt 做微调,然后加了一些工程技巧,得到了最后的 MobileNetV3。
最后再介绍一个同样是 Song Han 组最近的工作,Once for All: Train One Network and Specialize it for Efficient Deployment[Arxiv],直接 train 一个大网络,需要哪种网络直接去里面取就可以,将训练过程和搜索的过程解耦开来,相当于只需要 train 一次。
比较神奇的地方在于训完了之后不需要 fine-tune 就能取得很好的结果,应该是跟下面这种 progressive shrinking 的训练方式相关。如果再 fine-tune 精度会更高,openreview上的版本甚至比 MobileNetV3 高出 4 个点。
感觉是一个很好的思路,大部分 NAS 的主要时间到都花在验证/比较网络精度上,那么把这个时间都花在训练一个大网络上,然后再选所需要的小网络或许是一种更高效/性能更好的方式。Once for All 使用的一些技巧也比较多,推荐大家看一下原paper
最后再说一个Rethinking the Value of Network Pruning[ICLR'19]里面的结论,对于结构化的剪枝,Training---Pruning---Fine-tuning 的 pipeline 得到的精度并不如将目标网络 train-from-scratch 的精度高,也就是说剪枝的目标网络的结构设计其实最为重要,这也就是 NAS 正在做的事情。不过在 train-from-scratch 代价比较大的时候,pruning 和 fine-tuning 的策略也很重要,争取在计算量尽量少的情况下维持原有精度。