想象你是一家连锁餐厅的老板,想从一万道候选菜式中找出最受欢迎的那几道。传统做法是:每道菜都从零开始,单独请一批厨师、单独建一个厨房,花几个月时间试做、试吃、评价——这正是传统神经架构搜索(NAS)的困境:评估 1000 种架构,就要完整训练 1000 个模型,GPU 跑上几千年都嫌不够。ENAS(Efficient Neural Architecture Search)换了个思路:与其每次从零开始,不如只训练一个“超级厨房”,里面所有菜式共享同一批厨师、同一套锅碗瓢盆。每道新菜式只需从这个超级厨房里“借用”现成的厨艺组合,花几个小时就能完成评估。这就是权重共享——让所有候选架构共用一套超网络的权重,搜索效率因此提升了 1000 倍以上,单块 GPU 几小时就能完成架构搜索。本文将以“连锁餐厅”为主线比喻,带你完整掌握 ENAS 的权重共享机制。

岗位关联

掌握 ENAS 的核心思想,意味着你能在算力资源有限的实际场景下独立完成架构搜索任务,这是 AutoML 工程师和研究者的核心技能,也是进入高效神经网络设计领域的关键一步。

目录
  1. 可视化演示
  2. 从NAS到ENAS
  3. 权重共享核心
  4. 超网络训练
  5. 控制器采样
  6. ENAS与NASNet
  7. 搜索效率提升
  8. 实践与局限
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示四种事务隔离级别下的并发行为:脏读、不可重复读和幻读在不同级别下的表现差异。

本节配有交互动效(进入视口后自动加载,约 3KB)。

读未提交(Read Uncommitted) 事务T2可以读取T1未提交的数据(脏读) T1回滚后,T2读到的数据变为无效 ISO = READ UNCOMMITTED

从NAS到ENAS

传统神经架构搜索就像开一家“从零开始”的餐厅:每推出一道新菜,都要从买菜、备料、训练厨师、试菜开始。假设你有 1000 个候选菜式,每个菜式都需要一个完整的厨房团队从头磨合,那么光是试菜成本就会让你破产。这正是 2017 年 NAS(Neural Architecture Search)面临的核心困境——每一个候选架构都被当作独立的模型,从随机初始化开始完整训练,再评估其性能。

ENAS(Efficient Neural Architecture Search)的提出者 Pham 等人意识到了这个致命的效率问题。他们的洞察非常朴素却深刻:既然搜索空间中的架构之间存在大量重叠子结构,为什么不让这些子结构共享同一套已经训练好的权重?这就像你不再为每道菜单独组建厨师团队,而是先训练一个“全能厨师团队”(超网络),任何新菜式都从这个团队中调配人手,只需少量磨合就能试菜。

从数学视角看,传统 NAS 的搜索过程可以描述为:对每个架构 \( a \),从头训练得到权重 \( w_a \),然后评估验证集精度。这个过程的计算成本正比于候选架构数量。ENAS 则将目标转化为:训练一个超网络 \( \mathcal{G} \),所有架构都是它的子图。

回到我们的比喻:传统 NAS 相当于给一万道菜各建一个厨房,ENAS 则是先建一个包含所有厨艺的“超级厨房”,每道菜只需在超级厨房里换一套流程组合。这就是效率提升的根源——把“重复造轮子”变为“一次造轮子,反复换轮胎”。

CostENAS=Training(G)+∑a∼πθEvaluation(a;Ga)\text{Cost}_{\text{ENAS}} = \text{Training}(\mathcal{G}) + \sum_{a \sim \pi_\theta} \text{Evaluation}(a; \mathcal{G}_a)
这个公式说明:ENAS 只需完整训练一个超网络,每个子网络的评估只是“借用”超网络中对应子图的权重,因此成本大幅降低。
  1. 超网络训练这是主导成本项。超网络 \( \mathcal{G} \) 是一个包含所有可能算子的大模型,只需训练一次。
    Training(G)\text{Training}(\mathcal{G})
  2. 子网络采样与评估控制器按策略 \( \pi_\theta \) 采样子架构 \( a \),每个子架构的评估直接使用超网络中对应子图的权重。
    ∑a∼πθEvaluation(a;Ga)\sum_{a \sim \pi_\theta} \text{Evaluation}(a; \mathcal{G}_a)
  3. 总成本结构子网络评估不再需要从头训练,所以求和项的计算量远小于传统 NAS 中每个架构的完整训练成本。
    CostENAS≪∑aTraining(a)\text{Cost}_{\text{ENAS}} \ll \sum_{a} \text{Training}(a)

权重共享核心

超级厨房的精髓在于“同一批厨师,多种菜系”。假设你有川菜、粤菜、湘菜三个团队,全部共享同一个后厨、同一批基础食材和调料。每当要试一道新菜——比如“宫保鸡丁”,你只需要让川菜团队在这个共享后厨里做出来即可,不必为这道菜从零置办一套全新的厨房设备。ENAS 的权重共享做的正是这件事:所有候选子网络共享超网络中的同一套权重参数。

具体地,ENAS 将超网络定义为一个有向无环图(DAG),图中的每个节点代表一层特征图,每条边代表一个操作(如卷积、池化、恒等映射)。子网络是超网络的子图,即从 DAG 中选中一部分边和节点。关键之处在于:这些子网络在训练和评估时,使用的是超网络中全局共享的权重。例如,超网络中第 3 条边是一个 3×3 卷积,无论哪个子网络采样到这条边,它用的都是同一份卷积核参数。

这种设计彻底改变了搜索的成本结构。传统 NAS 中,评估 10000 个架构需要训练 10000 个独立模型;ENAS 中,10000 个架构共享同一套已训练好的权重,评估只需前向传播。你可以把每个子网络想象成“超级厨房里的一份菜谱”——菜谱可以无穷多,但后厨只有一套。

共享权重带来的最直接收益是:搜索过程从“训练+评估”变成了“只需评估”。就像餐厅试新菜不再需要从头培训厨师,而只是让现有厨师按新菜谱做一遍——成本自然降低了几个数量级。

wshared∈R∣E∣w_{\text{shared}} \in \mathbb{R}^{|\mathcal{E}|}
这里的 \( w_{\text{shared}} \) 表示超网络中所有边的共享权重集合,共 \( |\mathcal{E}| \) 条边。所有子网络都从这份共享权重中取值。
  1. 共享权重集合\( w_{\text{shared}} \) 存储了超网络中所有操作(边)的参数。它是唯一的、全局的。
    wshared∈R∣E∣w_{\text{shared}} \in \mathbb{R}^{|\mathcal{E}|}
  2. 边集合大小\( |\mathcal{E}| \) 表示超网络中边的总数。每条边对应一种可复用的操作(如 3×3 卷积、5×5 卷积等)。
    ∣E∣|\mathcal{E}|
  3. 子网络权重映射子网络的权重只是从共享集合中挑选对应边的权重,不需重新初始化。
    wa=Select(wshared,a)w_a = \text{Select}(w_{\text{shared}}, a)

超网络训练

训练超级厨房的挑战在于:厨师团队必须同时掌握所有菜系,但每次实际做的菜只有一道。如何平衡?ENAS 的回答是:每次训练迭代只采样一个子网络(子图),只更新这个子图包含的权重。在反向传播过程中,梯度只会回传到被采样子图上的边,未采样路径的梯度为零,权重保持不变。

从技术角度解释:超网络的训练实际上是一个“轮流训练子网络”的过程。在每一轮训练中,控制器根据当前策略 \( \pi_\theta \) 采样出一个子网络 \( a \),然后在训练数据上计算这个子网络的损失 \( L_a \)。反向传播时,只有 \( w_a \)(子网络涉及的共享权重)获得梯度并更新,超网络中其他边的权重被冻结。在下一轮,控制器采样另一个子网络,更新对应的另一部分权重。经过大量迭代后,超网络的每条边都被充分训练过。

这种交替训练策略有一个微妙但重要的效果:超网络中的每份权重都被多个子网络“使用”过,因此它们学到的是“对多种架构都有效的通用特征”。就像超级厨房的厨师——他们轮番做川菜、粤菜、湘菜,最终练出了一身“通吃”的本领。这种通用性正是权重共享能够高效评估未知子网络的基石。

超网络训练完毕,就像超级厨房的厨师团队已经练就了全能手艺。接下来要做的事情就轻松了——让控制器不断“点菜”(采样架构),然后快速试吃(评估性能),找出最好的菜式。

∇wLENAS=Ea∼πθ[∇waLa]\nabla_{w} \mathcal{L}_{\text{ENAS}} = \mathbb{E}_{a \sim \pi_\theta} \left[ \nabla_{w_a} \mathcal{L}_a \right]
公式说明 ENAS 优化的目标:期望意义下,所有采样子网络损失的梯度对共享权重的贡献。每个子网络只更新自己的那一份参数。
  1. 期望梯度\( \mathbb{E}_{a \sim \pi_\theta}[\cdot] \) 表示对所有可能采样的子网络取期望。每次迭代只采样一个子网络,用蒙特卡洛估计这个期望。
    ∇wLENAS=Ea∼πθ\nabla_{w} \mathcal{L}_{\text{ENAS}} = \mathbb{E}_{a \sim \pi_\theta}
  2. 子网络梯度\( \nabla_{w_a} \mathcal{L}_a \) 表示子网络 \( a \) 的损失对共享权重的梯度。这个梯度只对 \( w_a \) 非零,其他边的梯度为零。
    ∇waLa\nabla_{w_a} \mathcal{L}_a
  3. 梯度累加效果经过多轮迭代,不同子网络的梯度轮流更新共享权重,使超网络逐步收敛到“对多个子网络都有效”的参数状态。
    Ea∼πθ[∇waLa]\mathbb{E}_{a \sim \pi_\theta} \left[ \nabla_{w_a} \mathcal{L}_a \right]

控制器采样

超级厨房建好后,还需要一位“点菜师”来决定哪些菜值得试。在 ENAS 中,这个点菜师是一个 LSTM 控制器。它逐层地读入之前的决策结果,然后从候选操作集合中“选择”当前层的操作。这个选择过程本质上是采样——LSTM 输出每个候选操作的概率分布,然后从中采样一个操作作为当前层的决策。

控制器的工作方式非常像一个经验丰富的菜单设计师:它看一眼已经决定的菜品顺序(前面层的操作),然后根据经验决定下一层该用清蒸还是红烧(3×3 卷积还是 5×5 卷积)。每次生成的完整操作序列就是一个子网络架构。控制器通过策略梯度(Policy Gradient)算法更新自己的参数,以最大化期望奖励——这里的奖励就是子网络在验证集上的精度。

这构成一个双层优化循环:控制器(点菜师)负责生成架构,超网络(超级厨房)负责为架构提供权重并反馈性能信号。控制器从性能反馈中学习:哪些“菜谱”的组合更可能获得高分,于是逐渐提高这些动作的概率。如此往复,控制器会越来越倾向于生成高性能架构。整个过程就像点菜师通过不断试错,逐渐领会了什么样的菜品搭配最受欢迎。

在点菜师与超级厨房的持续互动中,搜索过程不断逼近最优架构。点菜师不需要真正理解每道菜的烹饪原理,只需要知道“这么做顾客评分高”。这就是强化学习的美妙之处——它是从反馈中直接学习策略,而无需显式建模。

J(θ)=Ea∼πθ[R(a)]J(\theta) = \mathbb{E}_{a \sim \pi_\theta} \left[ R(a) \right]
控制器的目标函数是最大化期望奖励。其中奖励 \( R(a) \) 是子网络 \( a \) 在验证集上的准确率。
  1. 策略网络\( \pi_\theta \) 是控制器的策略,参数为 \( \theta \)。它定义了在给定前序决策条件下选择下一个操作的概率分布。
    πθ(at∣a1:t−1)\pi_\theta(a_{t} | a_{1:t-1})
  2. 期望奖励\( \mathbb{E}_{a \sim \pi_\theta}[R(a)] \) 表示按照策略采样得到的子网络的期望性能。目标是让这个期望最大化。
    max⁡θEa∼πθ[R(a)]\max_{\theta} \mathbb{E}_{a \sim \pi_\theta} [R(a)]
  3. 策略梯度更新REINFORCE 算法用采样估计梯度。当子网络 \( a \) 的表现优于基线时,增加生成该架构的路径概率。
    ∇θJ(θ)≈1m∑i=1m∇θlog⁡πθ(a(i))R(a(i))\nabla_\theta J(\theta) \approx \frac{1}{m} \sum_{i=1}^{m} \nabla_\theta \log \pi_\theta(a^{(i)}) R(a^{(i)})

ENAS与NASNet

当 ENAS 的研究者把自家的超级厨房和 NASNet 的传统厨房做对比时,结果让整个领域震惊。NASNet 是 Google Brain 在 2017 年提出的 NAS 方法,它在 CIFAR-10 上搜索一个基础单元(cell),然后将单元堆叠迁移到 ImageNet。NASNet 取得了当时最先进的性能,但代价是 2000 GPU 天的计算量——用 500 块 P100 GPU 跑 4 天。而 ENAS 在几乎相同的搜索空间和性能水平下,只用了 4 GPU 小时——效率提升了 1000 倍。

两者为什么有如此大的差距?核心在于“是否从头训练”。NASNet 对每个候选单元都从头训练一个完整的模型,然后评估其精度;ENAS 则让所有候选单元共享超网络权重,评估一个单元只需一次前向传播。好比 NASNet 试一道菜就要重建一个厨房,ENAS 试菜只是让已有厨师按新菜谱做一遍。

ENAS 还引入了“宏搜索”与“微搜索”的区分。宏搜索是在整个网络层面搜索连接模式(网络有多少层、每层用什么操作);微搜索是搜索重复堆叠的单元结构(cell)。ENAS 的微搜索与 NASNet 的搜索空间非常相似——都在搜索一个 cell 的内部结构——但 ENAS 借助权重共享,可以在更大的搜索空间中搜索更久,同时消耗更少的算力。这使得 ENAS 不仅效率高,还能覆盖 NASNet 因算力限制而无法触及的更大架构空间。

这个对比揭示了权重共享的革命性意义:它把神经架构搜索从“只有大公司才玩得起”的奢侈品,变成了“一个研究者用一块 GPU 就能完成”的日常工具。NAS 由此从实验室走进现实工程实践。

Speedup=CostNASNetCostENAS≈1000×\text{Speedup} = \frac{\text{Cost}_{\text{NASNet}}}{\text{Cost}_{\text{ENAS}}} \approx 1000\times
在同等搜索空间和近似性能下,ENAS 比 NASNet 快约 1000 倍。这个差距完全来自权重共享——从“每菜一厨”到“一厨百菜”。
  1. 成本定义\(\text{Cost}_{\text{NASNet}}\) 是 NASNet 搜索期间所有候选子网络的完整训练成本之和;\(\text{Cost}_{\text{ENAS}}\) 是 ENAS 超网络的训练成本加上子网络的推理评估成本。
    CostNASNet=∑aTrain(a),CostENAS=Train(G)+∑aEval(a;Ga)\text{Cost}_{\text{NASNet}} = \sum_{a} \text{Train}(a), \quad \text{Cost}_{\text{ENAS}} = \text{Train}(\mathcal{G}) + \sum_{a} \text{Eval}(a; \mathcal{G}_a)
  2. 耗时数据NASNet 约 2000 GPU 天,ENAS 约 4 GPU 小时。换算为相同 GPU 单位(1 GPU 天 = 24 GPU 小时),ENAS 约 0.167 GPU 天。
    Speedup=20000.167≈11976\text{Speedup} = \frac{2000}{0.167} \approx 11976
  3. 学术报告口径实际论文报告的速度提升约为 1000 倍,取决于具体任务和 GPU 型号。
    Speedup≈1000×\text{Speedup} \approx 1000\times

搜索效率提升

超级厨房的价值不只是省成本,更在于它让“试菜”本身变得极度便宜。在 ENAS 的论文中,作者在 CIFAR-10 上仅用 4 GPU 小时就找到了一个在测试集上达到 2.89% 错误率的架构(带 cutout 增强),这个成绩接近甚至超越了当时许多手工设计架构和 NASNet 搜索出的架构。更令人惊喜的是,这个架构可以无缝迁移到 ImageNet 上——在 ImageNet 上训练后,达到了与 NASNet 可比的 top-1 精度。

这种效率提升对研究者和工程师有什么实际意义?想象一下,在过去,如果你想验证一个新想法(比如用某种新型卷积替换搜索空间中的某种操作),你得花 2000 GPU 天重新搜索一次,这意味着你几个月都不能用这块 GPU 做其他实验。而 ENAS 让你在吃一顿午饭的时间里就能完成一次搜索。这使得架构搜索的实验周期从“季度级”压缩到“小时级”,极大地加速了研究迭代速度。

当然,效率并非没有代价。ENAS 在搜索时对每个子网络的评估用的是共享权重的原生精度,而非重新训练后的精度。这意味着评估信号存在“噪声”——一个子网络的共享权重性能可能与它从头训练后的性能存在偏差。幸运的是,大量实验表明,这种偏差在实际中是可以接受的:在 CIFAR-10 上排名靠前的架构迁移到 ImageNet 后,表现依然出色。

效率提升的真正意义不只是“快”,而是改变了整个研究范式。当一次搜索的成本低到几乎可以忽略时,架构搜索就不再是“一次性投资”,而成为可以反复进行的日常实验工具——这为 AutoML 的大规模落地奠定了基石。

CIFAR-10 Test Error: 2.89%(4 GPU hours)ImageNet Top-1 Error: 26.1%(迁移后)\begin{aligned}&\text{CIFAR-10 Test Error: } 2.89\% \quad (\text{4 GPU hours}) \\&\text{ImageNet Top-1 Error: } 26.1\% \quad (\text{迁移后})\end{aligned}
ENAS 在 CIFAR-10 搜索出的架构直接迁移到 ImageNet,性能与 NASNet 相当,但搜索成本只有后者的千分之一。
  1. 搜索阶段ENAS 在 CIFAR-10 上搜索微单元结构,耗时 4 GPU 小时,验证集错误率 2.89%。这一步展示了单 GPU 可行。
    Search: CIFAR-10, 4 GPU hours, 2.89%\text{Search: CIFAR-10, 4 GPU hours, 2.89\%}
  2. 迁移阶段将搜索到的单元堆叠成更深的网络,在 ImageNet 上从头训练,top-1 错误率为 26.1%。从搜索到部署,不需要重新搜索。
    Transfer: ImageNet, Top-1 26.1%\text{Transfer: ImageNet, Top-1 26.1\%}
  3. 对比基线同样条件下,NASNet 需要 2000 GPU 天达到近似性能。ENAS 在效率上提升了三个数量级。
    vs. NASNet: 2000 GPU days→4 GPU hours\text{vs. NASNet: } 2000 \text{ GPU days} \rightarrow 4 \text{ GPU hours}

实践与局限

超级厨房虽好,但并非没有烦恼。首先,权重共享本身引入了一个微妙的偏差:超网络给出的性能排名并不总是与重新训练后的排名一致。就像一个全能厨师做川菜可能只发挥了七成水平(因为他的技能被平均分配给了多个菜系),而专门做川菜的厨师能发挥九成。这意味着 ENAS 选出的“最优架构”可能只是一个“好”架构,而不一定是真正的最佳架构。

其次,ENAS 存在“搜索与训练之间的差距”。搜索阶段子网络权重的性能是基于共享权重的,但最终部署时架构需要从零开始重新训练。如果共享权重的性能和重新训练后的性能相关性不强,搜索结果就会失真。研究者们发现,这种相关性在大多时候足够高,但在某些搜索空间配置下可能显著下降。

幸运的是,ENAS 的核心思想催生了一系列后续改进。DARTS 将搜索空间松弛为连续可微的形式,用梯度下降替代强化学习;ProxylessNAS 将权重共享的思想扩展到大规模目标检测任务;OFANet 提出渐进式收缩策略来缓解搜索与训练之间的差距。这些后续工作都建立在 ENAS 开创的“一次训练、处处复用”范式之上。在工程实践中,ENAS 已有多个成熟开源实现(如 NASLib、Auto-Keras 等),研究者可以快速上手并在自己的任务中复现或扩展。

从实践角度看,使用者需要牢记:权重共享是一把双刃剑。它让搜索效率提升了三个数量级,但同时也让搜索结果带上了“近似”的标签。理解这个权衡,才能正确地将 ENAS 应用到自己的研究任务中——在效率要求高、算力有限的场景下,ENAS 是一个理想的选择;在追求极致精度的场景下,则需要将其结果作为初始点进行二次优化。就像超级厨房能高效试菜,但最终确定招牌菜后,还是值得为它专门开一个独立厨房。

Weight Sharing⏟ENAS⟶Continuous Relaxation⏟DARTS⟶Progressive Shrinking⏟OFANet\underbrace{\text{Weight Sharing}}_{\text{ENAS}} \longrightarrow \underbrace{\text{Continuous Relaxation}}_{\text{DARTS}} \longrightarrow \underbrace{\text{Progressive Shrinking}}_{\text{OFANet}}
这条演进路径展示了 ENAS 权重共享思想如何开启后续一系列算法改进,形成了神经架构搜索的一个重要流派。
  1. ENAS 的开创权重共享首次将 NAS 的计算成本从数千 GPU 天降到几小时,奠定了高效搜索的基础。
    Weight Sharing→Efficient NAS\text{Weight Sharing} \rightarrow \text{Efficient NAS}
  2. DARTS 的改进将离散的架构搜索松弛为连续可微的架构参数 \(\alpha\) 搜索,用梯度下降替代强化学习控制器。
    Continuous Relaxation→min⁡α,wLval(w∗(α),α)\text{Continuous Relaxation} \rightarrow \min_{\alpha, w} \mathcal{L}_{\text{val}}(w^*(\alpha), \alpha)
  3. OFANet 的延伸通过渐进式收缩进一步缓解共享权重与独立训练之间的性能差距。
    Progressive Shrinking→Narrower Gap\text{Progressive Shrinking} \rightarrow \text{Narrower Gap}

AI 应用场景

移动端模型定制化搜索

阶段:模型架构设计与搜索

解决的问题:移动端设备(手机、IoT 设备)对模型有严格的体积和延迟限制。传统做法是工程师手工设计轻量级网络(如 MobileNet),每种硬件平台(NPU/GPU/DSP)都需要重新调参设计,耗费数月人力。ENAS 允许每个平台在各自的约束下做架构搜索,只需几小时即可找到满足延迟和精度要求的定制化架构。

具体案例:某手机厂商的 AI 算法团队需要对 3 款不同芯片平台的手机做图像分类模型部署。传统方式下每款平台需要工程师手调网络,耗时两周。使用 ENAS 后,团队以标准超网络为基础,为每款芯片设定延迟约束,在单台服务器上各跑 8 小时就得到了 3 个定制架构,每款精度比统一模型提升约 2%,部署周期缩短到 2 天。

AutoML 平台的高效架构搜索服务

阶段:自动化机器学习平台后端

解决的问题:AutoML 平台需要为不同行业客户(医疗、金融、零售)提供定制化模型服务,但每次搜索都消耗海量算力会让平台运营成本失控。ENAS 的权重共享策略使得平台可以在一次超网络训练后,用极低成本响应不同客户的定制化需求。

具体案例:某云厂商的 AutoML 平台引入 ENAS 作为核心搜索引擎。客户提交图片分类任务后,平台先训练一个通用超网络(约 3 小时),然后针对每个客户的数据集执行 30 分钟的子网络评估与挑选。相比之前的 NAS 方案(每客户 200 GPU 小时),平台整体算力成本降低了 90%,服务吞吐量提升 8 倍。

神经网络基础模块的快速创新验证

阶段:研究实验与论文验证

解决的问题:科研人员提出了新的卷积算子(如空洞卷积变体)或连接模式,想知道它在架构搜索框架下是否优于现有操作。使用传统 NAS 需要数月验证,使用 ENAS 只需将新算子加入超网络的候选操作集,重新训练几小时即可完成评估。

具体案例:某高校研究团队提出了一种门控卷积算子,希望验证其在自动搜索的架构中能否提升性能。团队成员在 ENAS 框架中将该算子加入候选操作空间,在 CIFAR-10 上重新运行搜索(约 6 小时),发现该算子确实被控制器高概率选中,后续在 ImageNet 迁移实验中也验证了提升效果。整个过程从想法到论文投稿仅用了 3 周。

Python 演示

python98 行
import numpy as np class SimpleENAS:    def __init__(self, n_layers=4, n_ops=3, hidden=16):        self.n_layers = n_layers        self.n_ops = n_ops        self.hidden = hidden        # 超网络权重:每层每个算子一个小矩阵        self.w_shared = [np.random.randn(hidden, hidden) * 0.1 for _ in range(n_layers * n_ops)]        # 控制器(简化版:均匀随机策略)        self.theta = np.ones((n_layers, n_ops)) / n_ops        # 经验记录        self.total_steps = 0     def sample_arch(self):        """从控制器策略中采样一个子架构"""        arch = []        for l in range(self.n_layers):            probs = self.theta[l] / self.theta[l].sum()            op = np.random.choice(self.n_ops, p=probs)            arch.append(op)        return arch     def forward(self, x, arch):        """在共享权重下执行子网络前向传播"""        h = x        for l, op in enumerate(arch):            idx = l * self.n_ops + op            h = np.tanh(h @ self.w_shared[idx])        return h     def train_step(self, x, y, arch, lr=0.01):        """对采样子网络执行一步梯度更新(SGD)"""        # 前向        h = x        cache = [h]        for l, op in enumerate(arch):            idx = l * self.n_ops + op            h = np.tanh(h @ self.w_shared[idx])            cache.append(h)        loss = 0.5 * np.mean((h - y) ** 2)         # 反向传播(仅更新本子网络涉及的权重)        grad_h = (h - y) / y.shape[0]        for l in reversed(range(self.n_layers)):            op = arch[l]            idx = l * self.n_ops + op            h_prev = cache[l]            grad_w = h_prev.T @ (grad_h * (1 - cache[l + 1] ** 2))            grad_h = (grad_h * (1 - cache[l + 1] ** 2)) @ self.w_shared[idx].T            self.w_shared[idx] -= lr * grad_w        self.total_steps += 1        return loss     def evaluate(self, x, y, arch):        """评估子网络在验证集上的损失(用共享权重)"""        pred = self.forward(x, arch)        return 0.5 * np.mean((pred - y) ** 2)     def search(self, x_val, y_val, n_iters=500):        """控制器策略梯度搜索(简化版:直接选最优历史架构)"""        best_arch = None        best_loss = float("inf")        for i in range(n_iters):            arch = self.sample_arch()            loss = self.evaluate(x_val, y_val, arch)            if loss < best_loss:                best_loss = loss                best_arch = arch        return best_arch, best_loss  np.random.seed(42)n_samples = 200X = np.random.randn(n_samples, 16)Y = np.sin(X.sum(axis=1, keepdims=True)) model = SimpleENAS() # 训练超网络:交替采样子网络并更新for epoch in range(50):    perm = np.random.permutation(n_samples)    for i in range(0, n_samples, 16):        batch_idx = perm[i:i + 16]        xb, yb = X[batch_idx], Y[batch_idx]        arch = model.sample_arch()        model.train_step(xb, yb, arch, lr=0.01) print("超网络训练完成, 总更新步数:", model.total_steps) # 搜索最优架构(用共享权重快速评估)best_arch, best_loss = model.search(X[:100], Y[:100], n_iters=200)# 用独立训练验证搜索结果(简化:用模型的最佳子网络再训练几步)X_val, Y_val = X[100:], Y[100:]final_loss = model.evaluate(X_val, Y_val, best_arch) print("搜索到的最优架构:", best_arch)print("验证集损失:", round(final_loss, 4))
目的:用 Numpy 实现一个玩具版 ENAS,演示超网络权重共享训练、子网络采样评估、控制器搜索三个核心流程。
  1. self.w_shared = [np.random.randn(hidden, hidden) * 0.1 ...]初始化超网络的共享权重池。这里是按“层 × 操作”预分配矩阵,后续所有子网络都从这份权重中取用。
  2. def sample_arch(self)控制器采样子架构。简化版用均匀策略,真实 ENAS 中这里是 LSTM 策略网络的采样动作。
  3. idx = l * self.n_ops + op将“层号 × 操作号”映射到共享权重池中的唯一索引。这是权重共享的核心——通过索引复用权重。
  4. def train_step(...)子网络的梯度更新。注意:反向传播只更新本次采样子网络涉及到的权重,其他共享权重不受影响。
  5. grad_w = h_prev.T @ (grad_h * (1 - cache[l + 1] ** 2))计算当前层权重的梯度,其中 (1 - h^2) 是 tanh 激活函数的导数项。
  6. model.train_step(xb, yb, arch, lr=0.01)交替执行“采样 → 训练”循环。每个 batch 采样不同的子网络,模拟 ENAS 的超网络训练流程。
  7. def evaluate(...)用共享权重直接评估子网络,不重新训练。这正是 ENAS 比传统 NAS 快千倍的原因。
  8. best_arch, best_loss = model.search(...)在验证集上搜索性能最好的子架构。控制器(即使这里退化为随机采样)通过反复评估找出最优架构。

常见误区

误区我理解 ENAS 就是先训练好一个模型,然后把它的权重复制给所有子网络,大家用完全一样的权重做预测,只是网络结构不同。

正解这个理解混淆了“共享”的含义。ENAS 中并不是所有子网络在所有时刻共享完全相同的最终权重。更准确地说,所有子网络共用同一个超网络的权重“池”,但每个子网络只从这个池中取走自己子图对应的那部分权重。训练过程中,不同子网络的梯度轮流更新超网络中各自对应的边,所以不同子网络最终使用的权重是超网络中不同子集的参数。就像共享厨房里,川菜厨师主要用的是辣椒区,粤菜厨师主要用海鲜区,大家共用厨房但不共用每一份食材。

为何常见:因为“权重共享”字面上容易理解为“所有权重对所有网络都相同”,忽略了共享的是“所有权重的存储空间”(超网络),而非“同一组数值被所有人使用”。

误区ENAS 既然帮我把架构搜出来了,那直接把超网络中这个子网络的权重拿出来用就行,不用再训练了。

正解ENAS 搜索阶段给出的是一个“好的架构”,而不是“训练好的模型”的最终权重。超网络中的共享权重是为了高效评估而训练的,其量化精度远低于独立训练后的模型。实际使用中,需要将搜索得到的架构用默认初始化重新训练(或从超网络权重热启动精调),才能得到最终部署模型。类比来说,超级厨房帮你决定了“宫保鸡丁”这个菜式值得推出,但真正开业时你还是得为这个菜配上专门的厨师精雕细琢。

为何常见:因为 ENAS 在搜索过程中用了训练好的共享权重做评估,容易让人误以为这些权重本身就能直接用于推理。实际上共享权重的目标是“能用”而非“好用”。

误区ENAS 既然用了自动化搜索,找出来的架构应该比人工设计的模型(如 ResNet)性能更好,不然为什么要用它?

正解ENAS 的核心价值在于“在极低算力成本下找到性能优秀的架构”,但它的搜索结果并不保证超越最好的人工设计模型。ENAS 在 CIFAR-10 上找到的架构与 NASNet 相当,但未必超过后续手工设计的 EfficientNet 等先进模型。搜索目标是给定搜索空间下的最优解,而搜索空间本身限制了性能上限。换句话说,ENAS 擅长的是在设定好的食材范围内找到最佳菜品组合,但它不能创造超出该范围的珍稀食材。

为何常见:因为对 AutoML 的宣传经常强调“自动找到超越人类的网络”,让人产生了搜索引擎一定优于人类专家的错觉。实际中搜索空间的设计仍然需要人类经验。

误区用超网络的共享权重来评估子网络,和把子网络独立训练后再评估,结果应该是一样的,所以 ENAS 的评估是准确的。

正解共享权重评估必然存在偏差。权重共享让每个子网络的权重都被“折中”了——它既不完全属于任何单一架构,也从未针对单一架构充分优化。因此共享权重下的性能排序可能偏离独立训练的排序。这正是后续 DARTS、ProxylessNAS 等算法着重缓解的问题。就像全能厨师做川菜可能不如专业川菜厨师地道,共享权重的子网络性能也低于独立训练的对应模型。

为何常见:因为权重共享的机制很自然,让人直觉认为“权重一样则评估等价”。忽略了权重的训练过程因为共享而相互耦合,导致评估公允性受损。

误区ENAS 之所以叫“高效”,关键是它的 LSTM 控制器设计。如果不使用 LSTM,权重共享就失效了。

正解权重共享是 ENAS 高效的核心,LSTM 控制器只是实现搜索策略的一种选择。后续研究甚至证明,使用随机搜索(无控制器学习)配合权重共享,在部分搜索空间上也能达到与 ENAS 相当的结果。控制器的角色是“引导搜索朝更有希望的方向探索”,而非权重共享机制本身。就像超级厨房的效率来自共享资源,而非点菜师的个人风格——换一个点菜师(甚至随机点菜)后厨房依然高效。

为何常见:因为论文中控制器是显眼的技术组件,而权重共享的机制相对隐蔽,初学者容易把文章标题的“高效”归功于最显眼的组件。

面试题

Q1. ENAS 与传统 NAS 在评估子网络时的核心区别是什么?

单选题 · easy

  • A.ENAS 对每个子网络都从头训练
  • B.ENAS 使用超网络的共享权重评估子网络← 正确答案
  • C.传统 NAS 使用共享权重评估子网络
  • D.两者没有本质区别

答案:B。ENAS 的核心创新是权重共享——所有子网络直接使用超网络中对应子图的权重进行快速评估,省去了从头训练的成本。选项 B 正确。选项 A 是传统 NAS 的做法,C 描述了相反的关系,D 显然错误。

Q2. 在 ENAS 的超网络训练中,梯度的回传范围是什么?

单选题 · easy

  • A.所有共享权重都获得梯度
  • B.当前采样子网络涉及的权重获得梯度← 正确答案
  • C.仅控制器参数获得梯度
  • D.没有任何参数获得梯度

答案:B。超网络训练时,每次只采样一个子网络进行前向和反向传播,只有该子网络涉及的共享权重被更新,未采样路径的梯度为零。B 正确。A 会破坏权重共享的设计逻辑,C 是控制器的更新方式,D 无意义。

Q3. ENAS 中控制器的角色是什么?

单选题 · mid

  • A.直接计算子网络的损失
  • B.对所有候选架构做穷举搜索
  • C.生成子网络架构的采样策略← 正确答案
  • D.存储超网络的共享权重

答案:C。控制器(通常为 LSTM)的任务是根据前序决策和验证集反馈,逐步生成当前层的操作选择,即定义了一个策略分布。C 正确。损失计算由超网络完成,A 错;控制器不做穷举,B 错;共享权重存储在超网络中,D 错。

Q4. ENAS 与 NASNet 相比最大的优势是什么?

单选题 · mid

  • A.搜索出的架构精度大幅领先
  • B.搜索成本降低了约 1000 倍← 正确答案
  • C.不需要 GPU 也能完成搜索
  • D.完全消除了搜索与训练的差距

答案:B。ENAS 在 CIFAR-10 上达到与 NASNet 相当的精度,但仅需 4 GPU 小时而非 2000 GPU 天,效率提升约千倍。B 正确。A 不符合事实(性能相当而非大幅领先),C 错误(仍然需要 GPU),D 错误(权重共享仍有偏差)。

Q5. 关于 ENAS 的权重共享机制,下列说法正确的是?

多选题 · mid

  • A.子网络是超网络的子图← 正确答案
  • B.所有子网络使用超网络中各自对应边的权重← 正确答案
  • C.每次训练迭代更新所有共享权重
  • D.子网络无需从零开始训练← 正确答案

答案:ABD。A 正确——超网络是包含所有候选操作的 DAG,子网络是它的子图。B 正确——子网络只取用自己子图对应的权重。C 错误——只更新当前采样子图涉及的权重。D 正确——这是权重共享的核心收益。

Q6. ENAS 搜索出的架构最终在目标任务上使用时,正确的做法是什么?

单选题 · mid

  • A.直接使用超网络中的共享权重部署
  • B.将架构重新训练后再部署← 正确答案
  • C.使用控制器的权重进行预测
  • D.不需要任何模型,直接用超网络推理

答案:B。超网络的共享权重是用于快速评估子网络的近似权重,并不是最终优化的模型参数。搜索出的架构需要重新训练(通常从头开始)才能获得最佳性能。B 正确。A 和 D 混淆了搜索权重与部署权重,C 误解了控制器的功能。

Q7. ENAS 相比 NASNet 使用相同搜索空间和近似性能时,效率提升千倍的原因有哪些?

多选题 · hard

  • A.避免了每个子网络的独立完整训练← 正确答案
  • B.所有子网络共享同一套超网络权重← 正确答案
  • C.评估子网络只需前向传播← 正确答案
  • D.控制器不再需要训练

答案:ABC。A、B、C 三者共同构成了 ENAS 的高效机制:权重共享(B)使得子网络不需要独立训练(A),而只需在共享权重上前向传播(C)。D 错误——控制器本身仍需要通过策略梯度训练来优化搜索方向。

Q8. 下列哪项是 ENAS 权重共享机制带来的“副作用”?

单选题 · hard

  • A.搜索效率提升千倍
  • B.子网络评估性能与独立训练存在偏差← 正确答案
  • C.控制器采样速度变慢
  • D.搜索空间显著变小

答案:B。权重共享让子网络的权重是“折中”的,从未针对单一架构充分优化,因此共享权重下的评估排名可能与独立训练后的排名不一致(选项 B)。A 是收益而非副作用;C 与权重共享无直接关系;D 错误——ENAS 的搜索空间与 NASNet 相当甚至更大。

Q9. ENAS 中控制器的训练使用什么方法?

单选题 · easy

  • A.梯度下降直接优化验证集精度
  • B.策略梯度最大化期望奖励← 正确答案
  • C.遗传算法选择最优架构
  • D.贝叶斯优化的期望改进

答案:B。控制器通过强化学习中的策略梯度(REINFORCE)算法更新参数,以最大化期望奖励(子网络的验证集准确率)。B 正确。A 是超网络的训练方式,C 和 D 是其他 NAS 方法使用的搜索策略,不是 ENAS 控制器的方式。

Q10. 关于 ENAS 的“搜索与训练之间的差距”,下列说法正确的是?

多选题 · hard

  • A.搜索阶段子网络使用共享权重评估← 正确答案
  • B.部署阶段架构需要重新训练← 正确答案
  • C.共享权重与重新训练的性能排名可能不一致← 正确答案
  • D.该问题在 ENAS 中不存在

答案:ABC。搜索与训练之间的差距正是权重共享评估的固有偏差:搜索用共享权重(A),部署需要重新训练(B),两者的性能排序可能不一致(C)。该问题推动了一系列后续改进算法(如 DARTS),并非不存在(D 错误)。