神经架构搜索(NAS)核心原理与多元方法解析
神经架构搜索(NAS)是自动化设计神经网络拓扑结构以在特定任务上实现最佳性能的过程。其目标是在有限资源和最小人为干预下设计架构。
根据某研究工作,我们来讨论NAS的通用框架。NAS本质上是一种搜索算法。它在一个由预定义操作(例如卷积层、循环层、池化层、全连接层等)及其连接组成的可能网络拓扑搜索空间中运行。然后,一个控制器从搜索空间中选择一系列可能的候选架构。候选架构被训练并根据其在验证集上的性能进行排名。该排名用于调整搜索并获得新的候选架构。该过程迭代进行,直到满足某个条件并提供最优架构。最优架构在测试集上进行评估。
通常,NAS算法的领域相当令人困惑。最流行的分类基于三个主要组成部分来描述NAS:a) 搜索空间,b) 搜索策略(涉及控制器类型和候选评估),以及c) 性能评估技术。有关更多细节,可以参考某机构的优秀综述。此外,某作者的另一篇优秀文章也是很好的额外资源。然而,最近的方法将搜索策略与评估步骤结合在一起,使得算法之间难以区分。因此,我们将仅基于搜索策略来探讨NAS。随着深入,我们将考察不同的搜索空间和评估技术。还需注意,许多实现尝试了不同类型的搜索策略,因此以下分类并非总是严格的。
搜索策略指的是用于在搜索空间中寻找最优架构的方法。我们可以根据搜索策略将NAS算法分为5个主要领域:
- 随机搜索
- 强化学习
- 进化算法
- 序列模型优化
- 梯度优化
随机搜索
最朴素的方法显然是随机搜索,它常被用作基线。这里,一个有效的架构完全随机选择,没有任何学习过程。
强化学习
NAS可以非常优雅地表述为强化学习问题。智能体的动作是生成神经架构,而智能体的奖励是性能评估。动作空间当然是搜索空间。因此,可以使用不同的强化学习方法来解决这个问题。
NAS的早期工作使用循环神经网络作为策略网络。RNN负责生成候选架构。然后,架构在验证集上进行训练和评估。RNN控制器的参数被优化以最大化预期验证准确率。如何优化?使用诸如REINFORCE和近端策略优化等策略梯度技术。
类似地,ENAS使用经过策略梯度训练的RNN控制器。值得注意的是,它是首批有效在架构间共享参数的工作之一。其直觉是将架构视为大型图的一部分,这种方法将在下面广泛看到。ENAS训练分两个交替步骤进行:a) RNN控制器用REINFORCE训练;b) 共享参数以典型的梯度下降形式训练。
另一项名为MetaQNN的成功工作,使用了带有ε-贪婪探索机制和经验回放的Q学习。
在继续之前,我们先讨论一下搜索空间。
全局搜索空间:NAS-RL寻找所有可能的操作组合,导致巨大且昂贵的搜索空间。它尝试组合操作以形成链式结构网络。搜索空间由以下参数化:a) 层数,b) 每个操作的类型,以及c) 每个操作的超参数。
后来,跳跃连接也被加入,允许了多分支架构,如ResNet或DenseNet类拓扑。
模块化搜索空间:为了解决全局空间问题,提出了基于单元的方法以“模块化”搜索空间。即,混合称为模块的不同层块。NASNet是该类别中最流行的算法。NASNet只学习两种类型的模块或“单元”:执行特征提取的正常单元和对输入进行下采样的约简单元。最终架构通过以预定义方式堆叠这些单元来构建。
基于单元的方法被广泛用于其他工作中。但通过单元进行模块化并不是唯一的替代方案。FPNAS通过交替优化块同时保持其他块固定来强调块的多样性。FBNet利用逐层搜索空间。网络中的每个可搜索层可以从逐层搜索空间中选择不同的块。
进化算法
遗传算法是优化网络架构的另一种方式。进化算法从模型种群开始。在每一步中,采样一些模型,并通过对其应用变异来“繁殖”产生后代。变异可以是局部操作,如添加一层、修改超参数等。训练后,它们被评估并添加回种群。该过程重复进行,直到满足某个条件。
GeNet提出了一种编码方法,将每个架构表示为固定长度的二进制字符串,这将用于标准遗传算法。AmoebaNet使用锦标赛选择进化算法,或者更准确地说,是其修改版本称为正则化进化。不同之处在于,每个模型的“年龄”也被考虑在内,倾向于选择更年轻的模型。注意,NASNet搜索空间在这里也被使用。
序列模型优化
在序列模型优化中,我们可以将NAS视为一个迭代构建越来越复杂网络的序列过程。一个代理模型评估所有候选模块(或单元)并选择一些有前景的候选模块。然后,它在验证集上评估生成网络的性能,并基于该性能更新自身。通过迭代,模型逐渐扩展并达到所需性能。
PNAS从NASNet搜索空间开始,并按渐进顺序搜索空间。每个单元最多可包含5个预定义块。它首先生成、训练和评估所有仅包含1个块的可能单元。然后扩展到包含2个块的单元。但这次,不是训练所有单元,而是使用代理模型来预测每个架构的性能。注意,代理模型是基于1块单元的验证性能训练的。该过程持续到5块单元。
DPP-Net遵循与PNAS非常相似的方法,但它也考虑了执行设备。给定执行搜索的设备,根据其内存大小和类似硬件特性设置约束。不满足约束的模型要么从候选列表中删除,要么使用帕累托最优性进行优化。
梯度优化和一次性方法
梯度优化方法在大多数情况下使用一次性模型。一次性模型,也称为超级模型或超级网络,通常是一个包含搜索空间中所有可能操作的单一大型网络,用于为其他候选网络生成权重。如何实现?在训练模型后,我们可以用它来采样“子架构”并在验证集上进行比较。在某种程度上,我们将参数共享的优势发挥到极致。
一次性网络通常使用梯度下降训练。问题是我们如何在离散搜索空间上运行基于梯度的方法?
连续搜索空间:但我们真的仅限于离散空间吗?全局和模块化搜索空间都假设我们有一组离散的可能解。一个令人兴奋的想法是将空间转换为连续且可微的形式。在这个方向上,DARTS通过将每个单元表示为有向无环图中的节点,以连续的方式松弛了NASNet的基于单元的空间。每个DAG由N个节点的顺序连接形成,并有两个输入节点和一个输出节点。通过将操作的离散选择表述为softmax来实现松弛;即连续的概率选择。
DARTS将NAS视为双层优化问题,因为它用梯度下降联合训练架构参数和网络权重。
以非常相似的方式,SNAS的搜索空间是来自完全可分解联合分布的独热随机变量集合。通过用具体分布松弛架构分布,使该搜索空间可微,从而能够使用梯度优化。另一方面,NAO将离散搜索空间映射到连续嵌入编码。这样,他们可以使用梯度优化获得最优嵌入编码。然后使用解码器将最优连续表示离散化为最终架构。
一次性方法:DARTS和NAO都属于一次性方法,因为它们使用超级模型推导最优架构。让我们探索其他一些方法。
SMASH训练一个称为HyperNet的辅助模型,而不是训练所有可能的候选,进一步减少了搜索空间。HyperNet用于为其他候选网络生成权重。如何实现?在每个训练步骤中,他们选择一个随机架构,并将其描述(以独热张量的形式)馈送到HyperNet以生成其权重。在训练整个系统后,他们在验证集上比较一堆采样架构及其生成的权重。然后“最佳”架构被正常训练。
ProxylessNAS提出了路径级剪枝的视角。它的另一个主要贡献是二值化架构参数的想法,以便一次只有一条路径处于激活状态。路径是否被剪枝的概率与权重参数联合学习。
因此,从具有所有候选路径的过参数化网络开始,训练交替执行以下两个步骤:
- 权重参数的训练通过每次仅采样一条路径并使用梯度下降训练它来进行。注意,在此步骤中,其余架构参数被冻结。
- 使用BinaryConnect训练架构参数,同时冻结权重参数。
一旦架构参数训练完成,他们通过剪枝冗余路径来导出最终架构。
单路径一次性构建了一个简化的超级模型,其中所有架构都是单一路径。通过将超级网络训练和架构搜索解耦为两个不同的步骤,他们还消除了之前看到的架构参数和权重的联合分布的需要。
超级网络优化通过简单地以统一方式采样路径完成,而实际的NAS则使用进化算法执行。
AlphaNet建立在先前工作的基础上,该工作使用就地知识蒸馏来处理NAS。通过蒸馏超级网络的知识,他们可以极大地提高子网络的性能。标准KD通常用KL散度表述,它量化了教师和学生之间的差异。AlphaNet更进一步,将α-散度应用于该问题,改进了超级网络的训练。在撰写本文时,根据Paperswithcode上显示的基准,AlphaNet在ImageNet数据集上实现了Top-1准确率。
另一个Top-1模型是BossNAS。BossNAS采用了一种称为集成自举的新颖自监督表示学习方案。作者首先将搜索空间分解为块。值得注意的是,原始工作仅专注于视觉模型,并使用了CNN和Transformer块的组合。超级网络也使用自监督进行训练,其方式类似于BYOL。两个孪生超级网络使用同一图像的一对增强视图学习表示,并最小化其输出之间的距离。子网络被训练以预测超级网络中所有采样模型的概率集成。概率集成被用作采样模型的评估指标。
神经架构迁移
NAT的作者提出了在NAS上下文中使用迁移学习的想法,将现有的超级网络迁移到特定任务的超级网络中。同时,他们还可以搜索能够更好地解决多个目标兴趣点的架构。从而将迁移学习与搜索过程相结合。
多目标指的是存在多个冲突目标。在多目标问题中,算法应通过提供目标间的最佳权衡来考虑所有目标。在NAS上下文中,目标的示例包括推断时间限制、内存容量、最终模型大小等。多目标NAS是一个快速发展的研究领域。
NAT分为三个部分:a) 准确率预测器,b) 进化搜索过程,以及c) 超级网络。整个过程如下:
- 从已训练超级网络列表开始,统一采样一组。
- 评估超级网络的性能。
- 然后构建准确率预测器,其目标是驱动搜索,同时考虑多个目标。
- 进化搜索提出一组有前景的架构。
- 架构返回原始超级网络列表,过程迭代直到满足终止条件。
使用神经网络智能的实现
为了更好理解,我们还将展示一个使用某中心的神经网络智能包实现NAS的示例。还有其他支持NAS的AutoML库,但NNI是目前最完整、维护得最好的。NNI支持多种方法,包括:基于PPO的方法、AmoebaNet、ENAS、DARTS、ProxylessNAS、FBNet、SPOS等。由于一次性模型始终优于其他技术,并且是当前的主要研究方向,我们将展示如何使用NNI执行它们。展示代码可以在此Colab笔记本中找到。请注意,它深受NNI库官方示例和教程的启发。
DARTS使用超级图作为其搜索空间。每个单元被视为一个DAG,它们被组合成一个多路径超级模型。为了声明一个单元,NNI提供了LayerChoice,它接受多个标准的PyTorch模块。这样,它在超级模型内部定义了多条路径。训练后,只有一条路径将被选中以形成最优架构。
self.conv1 = nn.LayerChoice([nn.Conv2d(3, 6, 3, padding=1), nn.Conv2d(3, 6, 5, padding=2)])
另一个选项是使用InputChoice模块,主要用于探索不同的连接。在我们的示例中,将使用跳跃连接。最终架构将要么保留跳跃连接,要么不保留。
self.skipconnect = nn.InputChoice(n_candidates=2)
x1 = self.skipconnect([x1, x1+x0])
超级图可以定义为典型的PyTorch模型,但需要使用NNI提供的包,而不是原始的PyTorch包。示例如下:
import torch.nn.functional as F
import nni.retiarii.nn.pytorch as nn
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.LayerChoice([nn.Conv2d(3, 6, 3, padding=1), nn.Conv2d(3, 6, 5, padding=2)])
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.LayerChoice([nn.Conv2d(6, 16, 3, padding=1), nn.Conv2d(6, 16, 5, padding=2)])
self.conv3 = nn.Conv2d(16, 16, 1)
self.skipconnect = nn.InputChoice(n_candidates=2)
self.bn = nn.BatchNorm2d(16)
self.gap = nn.AdaptiveAvgPool2d(4)
self.fc1 = nn.Linear(16 * 4 * 4, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
bs = x.size(0)
x = self.pool(F.relu(self.conv1(x)))
x0 = F.relu(self.conv2(x))
x1 = F.relu(self.conv3(x0))
x1 = self.skipconnect([x1, x1+x0])
x = self.pool(self.bn(x1))
x = self.gap(x).view(bs, -1)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
model = Net()
一旦我们声明了超级图,就可以使用DartsTrainer类定义NAS训练。DARTS需要一个评估每个候选架构的指标,以及典型的训练参数。在某种程度上,它类似于训练标准深度网络。
import torch
from nni.retiarii.oneshot.pytorch import DartsTrainer
def accuracy(output, target):
batch_size = target.size(0)
_, predicted = torch.max(output.data, 1)
return {"acc1": (predicted == target).sum().item() / batch_size}
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
trainer = DartsTrainer(
model=model,
loss=criterion,
metrics=lambda output, target: accuracy(output, target),
optimizer=optimizer,
num_epochs=1,
dataset=train_dataset,
batch_size=64,
log_frequency=10
)
trainer.fit()
训练后,可以获得最优架构。NNI API将以“突变”的形式提供它。这些突变显示了DARTS决定保留的单元拓扑结构。对于每个单元,我们将得到一个显示最佳拓扑的突变。
在我们的例子中,第一个卷积层将由第一个声明的块形成,而第二个由第二个块形成。跳跃连接也被发现能提供更好的结果,所以保留它们。
print('Final architecture:', trainer.export())
# Final architecture: {'_mutation_1': 0, '_mutation_2': 1, '_mutation_3': [1]}
NNI比我们在一篇文章中能够展示的要丰富得多,因此强烈建议尝试使用它。注意,某作者教授的机器学习建模生产管道课程的第一部分专门讲NAS,请务必查看。
结论
NAS研究仍处于早期阶段。基准测试也不是一项简单的任务。目前,我们有一些标准的基准测试,如ImageNet、NAS-Bench-201、CIFAR-10,但这个方向肯定还需要更多工作。最后,开源库,除了NNI之外,几乎很少涉及NAS作为一个问题。希望这篇综述能作为一篇入门文章,并激励更多的从业者将NAS作为他们的研究课题。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)或者 我的个人博客 https://blog.qife122.com/
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)
公众号二维码

公众号二维码


浙公网安备 33010602011771号