Neural Architecture Search (NAS)
神经架构搜索 (NAS) 通过搜索网络层和连接方式来自动设计神经网络。了解相关方法、计算成本以及通过 NAS 构建的模型。
神经架构搜索 (NAS) 是自动化机器学习 (AutoML)的一个分支,用于自动设计神经网络的结构。搜索算法会提出候选架构,估算每种架构在任务上的表现,并根据结果提出更好的架构,而不是由工程师手动选择卷积和其他层类型、网络深度、宽度及连接方式。优化目标通常是准确率,也常结合推理延迟、参数数量或目标硬件上的 FLOPs等成本指标。NAS 促成了多种广泛使用的计算机视觉主干网络,包括 EfficientNet 和 MobileNetV3。
NAS 的工作原理#
《机器学习研究杂志》中的一篇综述从三个维度对 NAS 方法进行分类:
- 搜索空间: 可以构建的架构集合,例如允许使用哪些操作类型、卷积核大小和跳跃连接,以及如何连接这些组件。许多方法会搜索一个小型重复单元,并将其堆叠多次,这样既能缩小搜索空间,也能让在小数据集上找到的单元迁移到大数据集。
- 搜索策略: 决定尝试哪些候选方案的算法,包括强化学习控制器、进化算法、基于梯度的方法和简单的随机采样。
- 性能估算策略: 如何在不完整训练的情况下为候选架构打分,例如减少训练轮数、使用更小的图像或数据集、预测最终准确率,或让候选架构共享权重。
从数千 GPU 日缩短到数小时#
早期 NAS 成本高昂,因为每个候选架构都要训练到收敛。在 Zoph 和 Le 2016 年的研究中,使用强化学习训练的循环控制器生成网络,搜索同时运行在 800 个 GPU 上;后续的 NASNet 工作使用 500 个 GPU、耗时四天,在 CIFAR-10 上找到一个可迁移到 ImageNet 的单元。AmoebaNet 通过正则化进化算法获得了相近结果,计算成本约为 3,150 GPU 日。ENAS让所有候选架构共享模型权重,并将候选架构视作一个大型网络的子图,将搜索时间缩短到单个 GPU 上不到 16 小时;DARTS则将离散的操作选择放宽为连续权重,使架构本身可以通过梯度下降在数个 GPU 日内完成优化。基准测试也让这一领域的热度有所降温:带提前停止的随机搜索在 Penn Treebank 和 CIFAR-10 基准上至少与 ENAS 表现相当。
硬件感知 NAS 与 NAS 构建的模型#
NAS 对实际应用影响最大的是面向边缘 AI的高效模型;这类模型必须在特定设备上平衡准确率和速度。MnasNet将真实手机上测得的延迟纳入搜索目标,在 Pixel 手机上实现了 75.2% 的 ImageNet top-1 准确率,耗时 78 毫秒;与 MobileNetV2 相比,速度快 1.8 倍,准确率高 0.5%。EfficientNet-B0 也来自类似的搜索,之后通过复合缩放扩展为 B1-B7 系列;MobileNetV3 则将硬件感知 NAS 与 NetAdapt 算法结合,为移动 CPU 进行调优。在目标检测方面,Deci 的 YOLO-NAS 模型通过其 AutoNAC 搜索引擎发现,并针对 INT8 量化后的低准确率损失进行设计;这些模型可通过 NAS 类在 Ultralytics 软件包中执行推理、验证和导出,但不支持训练。NVIDIA 后来收购了 Deci,这些模型也不再由原团队更新。
一个最简 NAS 示例#
以下示例使用最简单的搜索策略——随机采样,在 scikit-learn 手写数字数据集上对一个较小的多层感知机搜索空间进行探索。每个候选架构只训练 30 个轮次,作为低成本的性能估算,并在验证数据上评分:
import random
import warnings
from sklearn.datasets import load_digits
from sklearn.exceptions import ConvergenceWarning
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
warnings.simplefilter("ignore", ConvergenceWarning) # short training runs are the cheap estimate
X, y = load_digits(return_X_y=True)
X_train, X_val, y_train, y_val = train_test_split(X / 16, y, random_state=0)
# Search space: 1-3 hidden layers, each 8-128 units wide. Search strategy: 12 random samples
random.seed(0)
space = [8, 16, 32, 64, 128]
candidates = {tuple(random.choices(space, k=random.randint(1, 3))) for _ in range(12)}
# Performance estimation: train each candidate for only 30 epochs, then score it on validation data
scores = {}
for layers in candidates:
model = MLPClassifier(hidden_layer_sizes=layers, max_iter=30, random_state=0)
scores[layers] = model.fit(X_train, y_train).score(X_val, y_val)
worst, best = min(scores, key=scores.get), max(scores, key=scores.get)
print(f"{len(scores)} architectures: worst {worst} {scores[worst]:.3f}, best {best} {scores[best]:.3f}")12 次采样得到 10 种不同架构,其验证准确率从两层各含 8 个单元时的 0.398,到层大小为 128、128 和 16 个单元时的 0.978 不等,因此仅架构选择一项就能让准确率相差近 60 个百分点。完整的 NAS 运行会将获胜架构重新训练至收敛,并在单独的测试集上报告得分。










