Neural Architecture Search尝试理解

(...炼出一个丹方子)

Posted by tianchen on March 8, 2020

NAS

本文的宗旨是对NAS有一个感性的认知,对具体算法的细节可以慢慢补充

  • 组成部分
    • 搜索空间 Search Space
    • 策略 Action/Decision
      • 我们需要一个Controller去从Search Space中采样出优秀的架构
    • 策略评估
      • 需要一个Evaluator来评估获得的架构效果如何,我们希望它尽量快
    • 迭代Decision和Evaluation直到得出最后结果
  • 搜索空间: 包含了对NN的结构定义(有多少哪些层和他们的类型 / 层内的超参数(NxN卷积) / 前驱节点和后续节点直接链接关系(add/Concat)
    • 对搜索空间进行限制以提升速度 (切分为基本单元Cell或者Block)
    • 由于搜索空间是离散的,且搜索空间很大,无法得到一个显示的优化函数,所以是一个黑盒问题
  • 搜索策略(做出决策) - 本质上是一个超参数优化的问题
    • 随机搜索
    • 贝叶斯搜索
    • RL
      • Agent(Controller)完成对网络的结构设计,输出的(Action)是网络结构,Reward是性能最优化
      • 由于结构参数长度不固定,可以用RNN来建模
      • Exmaple: NASNet:预测出基本Block,将预测的Block分为普通(不改变输出结构)以及简约(减少输出尺寸)
      • Example:ENAS: Shared Weights来加速
    • 遗传算法 (Mutation-Based)
      • 将网络结构编码成二进制串(首先分为几个Stage,再在下面分为Node),首先随机若干个初始解,训练所有子网络,计算适应值,随机选择结构交叉,产生后代
      • 在初始化/样本选择/交叉/变异等多个子方向都有改进空间
    • 基于梯度的方法
      • 将离散问题连续化,更好的利用梯度信息
      • 做松弛化,将层之间的链接从0-1松弛为一定概率
      • Exmaple:DARTS,将网络单元表示为有向无环图,可以在搜索架构的同时获得结构参数
  • 策略评估
    • 核心目标:减少训练轮数
    • Example:
      • 在一个小的集(比如降采样的图像)上进行训练
      • 粗训,并排序(有错误可能)
      • 对结果进行预测(外推Extrapolation)
      • Weight-Sharing,避免TrainFromScratch

Paper Reading

  1. NAS with RL - Google Brain
    • 真的很早,算是开端了
    • 比cifar10上的baseline提了0.1个点,并且快了一丢丢1.05,以及其他的dataset-PennTreebank以及language modeling的task
    • 建立在认为NN的connectivity和structure可以被表达成一个variable-length string(可用RNN做embedding,也就是作为controller)
    • 将采样(RNN生成)出来的子架构进行训练,将Acc作为reward信号,通过Policy Gradient的方式回传去update controller(Original RNN) * 在relatedwork中讲到
    • hyper-param optimization只能够做到在fixed-length的space进行模型优化,且对good initial model比较依赖
    • Bayesian方法可以寻找一个“不定长”的架构,但是不是很有意义 * The controller in Neural Architecture Search is auto-regressive, which means it predicts hyperpa- rameters one a time, conditioned on previous predictions. This idea is borrowed from the decoder in end-to-end sequence to sequence learning. * search space
    • * RNN
    • 将RNN看作一个树的结构 * 不是这是不是语法错误…
  2. Accelerating NAS using performance prediction
    • 核心在于提出predictor来加速evaluation
    • 还搭了一个early stopping * 认为human是从training curve来观察的,本文parameterize了这个过程,训练regression model来预测acc * 对应的counterpart是Bayesian的一些方法
    • 目测是人工设计一些拟合learning curve的base function,然后用expensive的MCMC来拟合
    • 也有用高斯过程核函数的 * 说白了建模的是Training Curve
    • 输出val acc,输入是configuration,在每个time step
    • 做了一个SRM(Sequential Regression model)比如RBM,RandomForest等
  3. eNAS - Efficient Architecture Search by Network Transformation
    • Reusing Weight(Weight Manager)不需要from scratch来训练网络
    • metacontroller采样架构based on Network transformation
    • 依然是Rl Controller - Policy Gradient更新,其action是指导transformation
    • 网络的结构encoder依然是一个Bi-LSTM
    • (也可以认为是muation-based,不过指导mutation产生的不是遗传或者SA这类heuristic的方法,但是是RL-Agent)
      • 有两种Actor形式,Net2Wider或者Net2Deeper
      • Wider用一个公用的sigmoid分类器来生成反馈信息,确定是否在该时刻需要expand
      • Net2Deeper则是是否需要insert一个新的layer
      • Deeper用一个RNN来建模是否需要在某个位置插入一个新层
      • 可以插入新层的位置是预先固定的,依据pooling层的位置把网络分成几个block
  4. BOGCN - Multi-Object Neural Architecture Search via Predictive Network Performance Optimzation
    • Improving Sample Efficiency for Multi-Object
      • multi-object指的是speed-acc trade off
    • Bayesian Opt + GCN
      • BO(Bayesian Optimization) - finding global optim of black-box
      • 用GCN换了原本的BO中的GP,as surrogate of the objective function
        • gp是本身是self-conjugate的,因为其输入和输出同分布
        • 将GCN后面的一些fc层,换成了BLR(Bayesian Linear Regression)
      • GCN的优势在于能够更好的embed图的信息,以及能够处理变长节点
      • GCN只extract network embedding
    • One-shot NAS采用了weight sharing,但是不能保证optimal;Sample-based的更加稳定但是很慢
  5. Learning Transferable Architectures for Scalable Image Recognition
    • Cell-based Search Space (NASNet SS) * Convolutional Blocks Repeated many times * 一般分成N个Normal Cellh后面接一个Reduction Cell
    • Regularization Technique - Schedule Drop Path * 基于RNN的Controller
  6. SMASH: One-Shot Model Architecture Search through HyperNetworks
    • one-shot表示从一个HyperNet中取出架构,不需要training作evaluation,采用weight sharing
    • HyperNet - Training an auxiliary HyperNet to generate weights
      • 加速arch selection
      • 从binary coded到optimal architecture weights的mapping,只训练output layer(?)
      • 其训练是用gardient-based的方式来做到的
    • 选取arch来evluate的方式
      • Memory-bank view,将其作为binary vector
      • 是否意味着会遍历整个search space?
    • 文章中提到了说训练一个arch开始的部分是整体acc的一个insight
      • 一般的方法把arch的perf看作一个black box,用BO或者rs去搜索,也有early-stopping这样的策略
    • 能够抛弃其他所有的hyper-param以及dynamic-regulariaztion的东西
      • 比如lr schedule
      • 比如DropPath之类的东西
  7. Hierarchical Representations for Efficient Architecture Search
    • EA-based
    • hierarchical genetic representation
    • 模仿的是modularized design pattern * 采用了EA,指出最naive的random search也可以获得不错的效果 * flat representation - 将NN作为一个DAG
    • 小的graph motif组成一个大的graph motif
    • * Tournament Selection Search
  8. PNAS - Progressive Neural Architecture Search
    • NO RL or EA, Sequential-Model-Based Method
    • 内部也含了一个predictor
    • LSTM as encoder * Progressive (Simple 2 Complex)
    • Simpler Arch train faster * Cell-based Search Space
  9. Efficient Neural Architecture Search via Parameter Sharing
    • Shared-Weights
    • Controller在一个庞大的Compuation Graph上搜索Subgraph作为子图
    • 对于child modules Share Parameter
      * RNN Controller
      • 采样出链接关系
      • 以及node是什么
    • 这个controller是怎么训练的?
      • Policy Gradient?
  10. DARTS
    • 将原先的离散搜索,改为Differentiable方式(Relax the Search space to be Differentiable)
    • 核心在于如何修改Search Space * Search Space如何设计
    • 一个Cell是一个DAG,Node是一个latent representation(代表Feature Map),每个有向的边和某种操作(Op)有关
      • 每个op以softmax来relax,取各个实际操作(Max-pool/Conv/No)发生的概率
    • 认为每个cell有两个输入一个输出,对卷积层输入来自previous 2 layer(? 2度近邻居?)
    • N=7 Node,没有strided * Bi-level Optimization
    • Learn Arch and Weight at the same time
    • 注意实际对alpha导数是用的,而不是单纯的 \partial{L_val}/\partrial{\alpha}
      • *
  11. NAS Survey

  12. NAO-Neural Architecture Optimization
    • Discrete -> Continuos
      • 包含了一个encoder,将arch映射到一个连续空间,同时还搭配一个decoder
      • 还有predictor
    • 与此类似的是DARTS,说DARTS认为最好的arch是当前weight下的argmax,而NAO直接用一个decoder映射回模型
      • 还有一支是Bayesian Optimization,作者认为GP的性能于Covariance Function的设计强相关
    • Search Space设计
      • 两步,首先决定1)which 2 previous nodes as inputs 2)确定要用什么op
    • symmetric的design:为了保证symmetric的模型(实际上是一个模型)的embedding一致,predictor给出差不多的结果
      • 用了Augmentation(flip)来训练encoder
    • Encoder和Decoder都是LSTM,predictor是一个mean-pooling加mlp
    • 三者Jointly Train
      • 认为predictor could work as regularization去避免encoder只对应decoder的结果,而没有正常表征
        • 这一步和传统VAE中的加noise一致
    • 认为weight-sharing和NAO是complementary的
  13. SNAS-Stochastic NAS

  14. SemiNAS
    • 用Controller(其实是里面的predictor)去在大量无标注的arch上做标注(不经过Evaluation),将新的Data-Pair加入训练
    • 卖点是能够更快的找到比较好的架构,比EA之类的效率更高
      • 但是高的也不是很明显,怀疑是否是NAO带来的而不是Semi带来的(毕竟用自己推断出来的数据来训练自己(但是flow与Self-Supervised又不太一样))
    • 用NAO as example(因为它既可以用在conventional train from scratch也可以做Weight sharing)
  • Transfer Learning with Neural AutoML
    • Parallel Training on Multi-tasks, Transfer the search strategy
    • 当有了一个pretrained的controller的时候,只有task embedding需要更新
    • Generic SS (Learned task representation & Task-specific advantage normalization)
    • In standard single-task training of NAS, only the embedding of the previous action is fed into the RNN. In multitask training, the task embedding is concatenated to the action embedding. We also add a skip connection across the RNN cell to ease the learning of action marginal distributions
  • MetAdapt: Meta-Learned Task-Adaptive Architecture for Few-Shot Classification
    • 用MetaLearning+NAS来搜索出更适合Few-shot的架构
    • Differentiable-NAS
    • 发现FewShotLearning的backbone model是先越大越好,然后会差
      • 认为D-NAS可以mitigate overfitting
      • Follow DARTS - Arch as DAG
    • 与一半NAS不同,不是找到一个架构用
      • 找到能更快adapt到别的task的
      • 有一系列small networks,MetAdapt Controller,同时更新weights,修改connection
    • FewShotLearning
      • Metric Learning based
        • Learn a non-linear embedding into a metric space, use L2 distance for classification
          • (Some change L2 disatnce with a implicit learned function/GNN)
        • Could improve when adding semantic information
      • Generative Based
        • 或者说是augmentation-based
        • 设计到一些transfer相关的一些东西
      • Meta Learning - learn a learning stragegy easily adapted to other few-shot tasks
        • trained on a set of few-shot tasks (episodes)
        • 另外一支是gradient-based
          • MAML
          • MetaSGD
      • MetAdapt的flow
        • arch as DAG , feature map as node / op as edge
        • Task-Adaptive Block
  • 这个图的配色不错

## Baselines

AW_NAS

  • ROOT下的base.py定义了MetaClass Components供其他类实现
    • Component包含了:
      • 有Logger
      • 有Set/Get State
      • 以及config
  • ROOT下的Plugin.py ❓ 管理诸如controller/dataset/evaluator取什么组件的,或者说是用来Manage各个Module的?

Search Space

实现了一些具体的SearchSpace

  • common.py 中包括了对SearchSpace相关的一些定义
    • SearchSpace <== CellSearchpace <== CNN/RNNSearchSpace
      • 提供了init和一些get以及plot方法
    • 包含了CNN和RNN的
    • (没有实现Hierarchy)

Datasets

从Dataset中取数,实现了一个DataSet类

  • BaseDataSet <== Cifar/ImageNet
    • 实现了一些split/get_name等方法
  • ❓:PTB.py - 看上去是维护了一些语料库?(为什么要这么封装)

Rollout

含义是NetworkStructure的一个编码,是Conreoller/WeightManager/Trainer都需要的一个InterfaceClass,跨组件之间交流的对象

  • 其中__init__.py内调用了Utils当中的expect方法,列举了每个文件中应该包含的模块
  • BaseRollout <== Rollout / DifferentiableRollout – 描述的是采样出来结构的信息
    • ❓ 一个Rollout和其SearchSapce相关(合理),但是内部为何会有RandomSample方法呢?
    • 一个Rollout包含了
      • 属性
        • arch
        • info
        • SearchSpace
        • candidate_net
      • 方法
        • random_sample_arch
        • 一些plot和get方法
        • ——– Differential 特有的 —————
          • discrete_arch_and_prob
            • 调用了parse:得到最终的DiscreteRollout
            • @Propoerty装饰器将类方法伪装为类属性(只有一个self参数),产生的原因是为了保持一个属性getter和setter方法的精简(如果不用getter/setter又暴露在外面)
    • BaseRollout中有一些抽象方法等待子类去继承
  • Dense.py内比较特殊,定义了Dense的SearchSapce以及Dense的Rollout(继承了Rollout而不是BaseRollout)
  • MNasNet同理
    • ❓ 为啥有个OFA的…
  • Mutation.py 包含了一系列与Mutation-Based相关的组件
    • objetc <== Population (物理意义上是SearchSpace的子集,Mutation中产生的模型集合)
    • CellMutation
    • BaseRollout <== MutationRollout
  • repr方法显示Obj的属性 (那我为啥还在用vars?)

Controller

  • 负责采样(Sample)出一个Neural Architecture(网络架构)
  • Component <=== BaseController
    • 属性
      • SearchSpace
      • RolloutType
      • Mode
    • 方法
      • SetMode
      • Sample(Sample a Rollout From Population(SearchSpace))
      • Step(Upadte Controller)
      • Summary / Save / Loads
  • Population.py(❓不是说没有实现吗?)
    • 包含了Mutation-Based的Agent训练方法
    • ❓文档中说包含了Bayesian方法,是否是RandomSamplerttr
      • Component <== BaseMutaionSampler <== RandomMutationSampler
        • 内部重要的是sample_mutation方法
      • BaseController <== Population Controller
        • 有一个mutation_Sampler的属性(BaseSampler)
        • ScoreFunction相关
        • ChooseParents
  • dense_controller(Unfinished)
  • BaseController/nn.Module <== DiffController
    • 属性
      • use_prob,是直接使用Probabilty还是relax Sampling
      • gumble_hard:对RelaxedVector前向使用GumbleSoftmax
      • gumble_Temperature
      • _init_nodes / edge_list
    • 方法
      • forward - 执行sample
      • Calc Gradient & Choose Loss
      • Summary
  • rl_networks.py
    • ❓ SCEDULABLE_ATTR 表示?
    • Components <== BaseRlController <== BaseLSTM <== AnchorControlNet / EmbeddedControlNet
      • 属性
        • 一些描述LSTM大小的参数
      • 方法
        • forward - Sample
  • rl_agent.py
    • Component <== BaseRLAgent
      • 属性
        • Controller
      • 方法
        • Step
    • BaseRLAgent <== PGAgent (Policy Gradient)
      • 方法
        • step / _step 方法的区别 ❓
    • BaseRLAgent <== PPOAgent (Proximal Policy Optimization)
  • rl.py
    • BaseRLAgent / nn.Module <== RLController
      • 属性
        • SearchSapce
        • RolloutType
        • ControllerNetwork
        • RLAgent
        • Mode (Train/Eval)
      • 方法
        • step - 计算loss
        • Sample - 获取Rollout

WeightManager

与Evaluator联系,因为TrainFromScratch太慢了,所以需要一定程度上ShareWeights或者以其他方式利用之前的Weights

  • base.py
    • Component <== BaseWeightManager
      • 属性
        • SearchSpace
        • RolloutType
      • 方法
        • Assemble_Candidate(via Rollout)
        • Step - Update Weight Manager Accoding to Gradients
    • nn.Module <== CandidateNet
      • Different Forward Methods
      • Get Gradient
      • Train/Eval Queue
  • share.py - **
    • BaseWeightManager / nn.Module <== SharedNet
      • ❓ use_stem?
    • SharedCell <== nn.Module
    • SharedOp <== nn.Module
  • SuperNet.py
    • CandidateNetwork <== SubCandidateNet
    • SharedNet <== SuperNet - (Cell—Based SuperNet)
  • DiffSuperNet.py
    • CandidateNet <== DiffSubCandidateNet
  • dense.py
    • BaseWeightManager <== DenseMorphismWeightManager
      • 属性
        • NoiseType
      • 方法
        • Assemble Rollout
        • add noise
        • widen
        • Deepen

Trainer

用来调和(Orchestra)整个搜索过程

  • GenoType ❓

  • async.py
    • 多进程相关
  • base.py
    • Component <== BaseTrainer
      • 属性
        • Cotroller
        • Evaluator
        • RolloutType
      • 方法
        • Setup
  • simple.py
    • BaseTrainer <== SimplerTrainer
      • _evaluator_update
      • _controller_update
      • _backward_rollout_to_controller
      • Train
      • Test
      • derive

Evaluator

用来测试Sample出来的Rollout(或者说是CandidateNetwork❓这两者是不是共同,或者说CandidateNetwork在什么时候会选择)

  • base.py
    • Component <== BaseEvaluator
      • 方法
        • Evaluate_Rollout
        • Upadte Rollout / update evaluator
  • mepa.py
  • ❓ MEPA是啥?
    • Component/nn.Module <== LearnableLROutPlaceSGD
    • BaseEvaluator <== MepaEvaluator
  • tune.py
    • BaseEvaluator <== TuneEvaluator

OPs

其中列举了一些NN Operator

  • Baseline_Ops.py
    • 一些常见网络的Block,比如VGG/MobileNet等
  • OPs.py
    • 一些自定义的Block和NN组件
      • 类似Conv-BN-Relu

Objectives

指定不同的任务的

  • ❓Perfs的全程?这个模块的意义?描述了什么东西,以及在社么场景下使用(这些问题概括下来好像就是我完全没懂这个是干啥的)

Utils

Final