DARTS算法笔记(论文+代码)
DARTS: DIFFERENTIABLE ARCHITECTURE SEARCH
论���链接:DARTS 论文代码:DARTS-code 本文主要对DARTS算法进行学习,重点关注算法在CIFAR-10, ImageNet(分类问题)的研究。 DARTS通过两次近似,将问题简单化,以减少GPU计算天数,局部最优近似全局最优,有限差分近似求梯度。
摘要:
在CIFAR-10、ImageNet、Penn Treebank和WikiText-2上进行的大量实验表明,我们的算法在发现用于图像分类的高性能卷积架构和用于语言建模的循环架构方面表现出色,同时比最先进的不可微技术快几个数量级。我们的实现已经公开,以促进对高效架构搜索算法的进一步研究。
DARTS算法的目的是通过求近似梯度来寻找一个架构参数α,使得计算资源得到缓解,同时在一定程度保证准确率。
1.引言
作者提到,先进的神经网络一般都是专家付出了巨大的努力设计出来的,而现在已经开始流行神经网络架构搜索,也就是让算法针对具体问题,自动设计出一个神经网络出来。神经网络架构搜索在分类问题和目标检测问题上取得了突破。
通过算法让计算机自己设计一个最优网络出来,也许实验的效果是很好的,但非常耗时,文献指出,如CIFAR-10和ImageNet的最先进架构需要2000个GPU天的强化学习(RL) 或3150个GPU天。这里的GPU天数,大多数论文没有统一的标准,有的1080,有的v100,有的多块GPU,有的一块,不过不管怎样,这都太耗费时间了。之所以耗费时间是因为这些主流方法(强化学习,启发式算法,进化算法等),将架构搜索问题视为离散域上的黑盒优化问题,而这个问题:解空间巨大、目标函数评估耗时、局部最优和全局最优的存在以及算法参数调整等因素,通常需要耗费更多时间。
这让普通实验室情何以堪啊,谁有这么多卡啊。不过DARTS来解决这个问题。
DARTS不再搜索一组离散的候选体系结构(通常涉及在一组预定义的架构中进行选择,以找到性能最优的架构。因为它需要对每个候选架构进行单独的评估。如果100个结构,做100次实验啊。这就是在排列组合实验,遍历是最耗时的。)
时间不等人。DARTS的方式是将搜索空间放宽为连续的,这样体系结构就可以通过梯度下降来优化其验证集的性能。 经过设计的DARTS算法不仅计算耗时少,而且精度也具有竞争力。
在第三章的实验中,证明了DARTS算法在不同领域的竞争力:分类和语言建模。
由于机器和方向原因,本文暂且针对原文CIFAR10进行了测试。
主要贡献: 1.提出了一种基于双层优化的可微网络结构搜索算法,该算法既适用于卷积网络结构,也适用于循环网络结构 2.通过对图像分类和语言建模任务的大量实验,我们表明基于梯度的架构搜索在CIFAR-10上获得了极具竞争力的结果,并且在PTB上优于目前的技术水平。这是一个非常有趣的结果,因为到目前为止,最好的架构搜索方法使用的是不可微搜索技术,例如基于RL或进化。 3.我们实现了显著的效率提升(将架构发现的成本降低到几个GPU天),我们将其归因于使用基于梯度的优化,而不是不可微搜索技术。 4. 我们证明了DARTS在CIFAR-10和PTB上学习的架构可以分别转移到ImageNet和WikiText-2上。
这里重点在三个: 双层优化问题,基于梯度的架构搜索,将成本降低到几个GPU天。
看完后续才明白这里的巧妙之处。
2. DARTS(DIFFERENTIABLE ARCHITECTURE SEARCH)
本章详细介绍了DARTS算法,主要三部分, 2.1 描述搜索空间; 2.2 为搜索空间引入了连续松弛方案,使其可微分的学习目标,进而用于结构及其权重的联合优化; 2.3 提出了一种近似技术,使该算法在计算上可行且高效
2.1 搜索空间 SEARCH SPACE
作者同样是在前人的工作基础上进行的神经网络架构搜索的研究。这里简单提一句,不管是分类问题CNN还是自然语言问题RNN,都需要一个网络架构。之前都是人工设计,即使现在用NAS(神经网络架构搜索)找到合适的网络架构,同样是借助了人工的经验。
网络结构就需要有基础的模块,如卷积Conv,池化pooling等,将这些模块通过合理的方式搭建起来完成相应的任务。
如下图,之前NAS工作(Learning transferable architectures for scalable image recognition)就设计了两种基础的单元: 即Normal Cell 和 Reduction Cell。如下图,一个分类图像经过这些基础模块,最终完成分类任务。因此,这里DARTS的任务就是设计这两种Cell,只要设计好这两种Cell,就能够堆叠完成工作。
作者设计的cell如下: 整体Cell:单元是由N个节点的有序序列组成的有向无环图。
输入节点:两个。分别前两层(i-1和i-2层) 中间节点:四个。每个中间节点的计算都是在其所有前节点的基础上累计计算的。 如节点1 = 需要计算Input Node 0 + Input Node 1 + 中间0节点。其他中间节点按照此规律进行。 输出节点:所有中间节点在通道维度上的Concat操作所得。
有了这个基础的搜索空间,需要想办法确定中间节点这些边(即操作)和连接方式。第二节进行了介绍。
2.2 连续松弛和优化 CONTINUOUS RELAXATION AND OPTIMIZATION
因此现在的问题转化为是如何确定中间节点之间的操作(也就是那些边)。
在下图中,原文给出了这个方法的总结图。
(a):开始这些边(操作)是未知的 (b):好好好,未知是吧。直接把这些边(操作)全部加上。 ©:怎么确定到底是哪个边。通过求解一个双层优化问题对混合概率和网络权值进行联合优化。 (d):通过混合概率,权重最大的,确定最终的边,进而确定最后的架构。 其实在后面可以知道,这里每个节点最后选择了两条边。 这个问题转为为公式(2):
i节点和j节点之间的混合操作的结果 = 操作集合中的每个操作(卷积,池化等) 处理i节点特征图,再对所有结果加权求和。
在代码中,这些操作在genotypes.py文件中:
PRIMITIVES = [ 'none', 'max_pool_3x3', 'avg_pool_3x3', 'skip_connect', 'sep_conv_3x3', 'sep_conv_5x5', 'dil_conv_3x3', 'dil_conv_5x5' ]
因此,现在的问题再次得到了转化,架构搜索的任务简化为学习一组连续变量:α α = { α ( i , j ) } ( 3 ) \alpha = \{ {\alpha ^{(i,j)}}\} (3) α={ α(i,j)}(3)
此时α我们称之为架构参数。在搜索的最后,在搜索结束时,通过将每个混合操作o(i,j)替换为最可能的操作,可以得到一个离散的架构,也就是图1的d图。这可以通过找到权重最大值实现(公式4)。 o i , j = arg max o ∈ σ α o ( i , j ) ( 4 ) {o^{i,j}} = \arg {\max _{o \in \sigma }}{\alpha _o}^{(i,j)}(4) oi,j=argo∈σmaxαo(i,j)(4)
将搜索空间松弛化后(中间节点的所有操作边),出现了新的参数,架构参数α。
因此,现在的架构搜索学习目标为:学习架构参数α和权重w
而这两个参数的学习问题进一步讲,就是优化损失函数,让损失函数最小的情况下,找到这个最佳架构参数α和权重w。
DARTS算法的核心就是利用梯度下降法,优化验证集损失函数,找寻最佳架构参数α和权重w**。
而训练集和验证集的损失函数与这两个参数之间的关系及约束条件是:
min α L v a l ( ω ∗ ( α ) , α ) s . t ω ∗ ( α ) = a r g m i n ω L t r a i n ( ω , α ) ( 5 ) \begin{array}{l}\mathop {\min }\limits_\alpha {L_{val}}({\omega ^*}(\alpha ),\alpha )\\s.t{\omega ^*}(\alpha ) = argmi{n_\omega }{L_{train}}(\omega ,\alpha )\end{array}(5) αminLval(ω∗(α),α)s.tω