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
- 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看作一个树的结构 * 不是这是不是语法错误…
- 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等
- 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
- 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的更加稳定但是很慢
- Improving Sample Efficiency for Multi-Object
- 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
- 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之类的东西
- 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
- 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
- Efficient Neural Architecture Search via Parameter Sharing
- Shared-Weights
- Controller在一个庞大的Compuation Graph上搜索Subgraph作为子图
- 对于child modules Share Parameter
* RNN Controller -
- 采样出链接关系
- 以及node是什么
- 这个controller是怎么训练的?
- Policy Gradient?
- 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}
- *
- 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一致
- 认为predictor could work as regularization去避免encoder只对应decoder的结果,而没有正常表征
- 认为weight-sharing和NAO是complementary的
- Discrete -> Continuos
- SemiNAS
- 用Controller(其实是里面的predictor)去在大量无标注的arch上做标注(不经过Evaluation),将新的Data-Pair加入训练
- 卖点是能够更快的找到比较好的架构,比EA之类的效率更高
- 但是高的也不是很明显,怀疑是否是NAO带来的而不是Semi带来的(毕竟用自己推断出来的数据来训练自己(但是flow与Self-Supervised又不太一样))
- 用NAO as example(因为它既可以用在conventional train from scratch也可以做Weight sharing)
## Baselines
AW_NAS
- ROOT下的base.py定义了MetaClass Components供其他类实现
- Component包含了:
- 有Logger
- 有Set/Get State
- 以及config
- Component包含了:
- ROOT下的Plugin.py ❓ 管理诸如controller/dataset/evaluator取什么组件的,或者说是用来Manage各个Module的?
Search Space
实现了一些具体的SearchSpace
- common.py 中包括了对SearchSpace相关的一些定义
- SearchSpace <== CellSearchpace <== CNN/RNNSearchSpace
- 提供了init和一些get以及plot方法
- 包含了CNN和RNN的
- (没有实现Hierarchy)
- SearchSpace <== CellSearchpace <== CNN/RNNSearchSpace
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又暴露在外面)
- discrete_arch_and_prob
- 属性
- 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
- Component <== BaseMutaionSampler <== RandomMutationSampler
- 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)
- Component <== BaseRLAgent
- rl.py
- BaseRLAgent / nn.Module <== RLController
- 属性
- SearchSapce
- RolloutType
- ControllerNetwork
- RLAgent
- Mode (Train/Eval)
- 方法
- step - 计算loss
- Sample - 获取Rollout
- 属性
- BaseRLAgent / nn.Module <== RLController
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
- Component <== BaseWeightManager
- share.py - **
- BaseWeightManager / nn.Module <== SharedNet
- ❓ use_stem?
- SharedCell <== nn.Module
- SharedOp <== nn.Module
- BaseWeightManager / nn.Module <== SharedNet
- SuperNet.py
- CandidateNetwork <== SubCandidateNet
- SharedNet <== SuperNet - (Cell—Based SuperNet)
- DiffSuperNet.py
- CandidateNet <== DiffSubCandidateNet
- dense.py
- BaseWeightManager <== DenseMorphismWeightManager
- 属性
- NoiseType
- 方法
- Assemble Rollout
- add noise
- widen
- Deepen
- 属性
- BaseWeightManager <== DenseMorphismWeightManager
Trainer
用来调和(Orchestra)整个搜索过程
-
GenoType ❓
- async.py
- 多进程相关
- base.py
- Component <== BaseTrainer
- 属性
- Cotroller
- Evaluator
- RolloutType
- 方法
- Setup
- 属性
- Component <== BaseTrainer
- simple.py
- BaseTrainer <== SimplerTrainer
- _evaluator_update
- _controller_update
- _backward_rollout_to_controller
- Train
- Test
- derive
- BaseTrainer <== SimplerTrainer
Evaluator
用来测试Sample出来的Rollout(或者说是CandidateNetwork❓这两者是不是共同,或者说CandidateNetwork在什么时候会选择)
- base.py
- Component <== BaseEvaluator
- 方法
- Evaluate_Rollout
- Upadte Rollout / update evaluator
- 方法
- Component <== BaseEvaluator
- 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
- 一些自定义的Block和NN组件
Objectives
指定不同的任务的
- ❓Perfs的全程?这个模块的意义?描述了什么东西,以及在社么场景下使用(这些问题概括下来好像就是我完全没懂这个是干啥的)