"test/gemm_add/test_gemm_add.hpp" did not exist on "753cef783fe70b753f42bc6b4d008400980dc1b4"
NasGuide.rst 5.5 KB
Newer Older
kvartet's avatar
kvartet committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
One-Shot NAS 算法
=======================

除了 `经典 NAS 算法 <./ClassicNas.rst>`_,还可以使用更先进的 One-Shot NAS 算法来从搜索空间中找到更好的模型。 One-Shot NAS 算法已有了大量的相关工作,如  `SMASH <https://arxiv.org/abs/1708.05344>`__\ , `ENAS <https://arxiv.org/abs/1802.03268>`__\ , `DARTS <https://arxiv.org/abs/1808.05377>`__\ , `FBNet <https://arxiv.org/abs/1812.03443>`__\ , `ProxylessNAS <https://arxiv.org/abs/1812.00332>`__\ , `SPOS <https://arxiv.org/abs/1904.00420>`__\ , `Single-Path NAS <https://arxiv.org/abs/1904.02877>`__\ ,  `Understanding One-shot <http://proceedings.mlr.press/v80/bender18a>`__ and `GDAS <https://arxiv.org/abs/1910.04465>`__ One-Shot NAS 算法通常会构建一个超网络,其中包含的子网作为此搜索空间的候选项。每一步,会训练一个或多个子网的组合。

当前,NNI 支持数种 One-Shot 方法。 例如,``DartsTrainer`` 使用 SGD 迭代训练体系结构权重和模型权重,``ENASTrainer`` `使用控制器训练模型 <https://arxiv.org/abs/1802.03268>`__ 新的、更高效的 NAS Trainer 在研究界不断的涌现出来,NNI 会在将来的版本中实现其中的一部分。

使用 One-Shot NAS 算法进行搜索
-----------------------------------

每个 One-Shot NAS 算法都实现了 Trainer,可在每种算法说明中找到详细信息。 这是如何使用 ``EnasTrainer`` 的简单示例。

.. code-block:: python

   # 与传统模型训练完全相同
   model = Net()
   dataset_train = CIFAR10(root="./data", train=True, download=True, transform=train_transform)
   dataset_valid = CIFAR10(root="./data", train=False, download=True, transform=valid_transform)
   criterion = nn.CrossEntropyLoss()
   optimizer = torch.optim.SGD(model.parameters(), 0.05, momentum=0.9, weight_decay=1.0E-4)

   # 这里使用 NAS
   def top1_accuracy(output, target):
       # 这是ENAS算法要求的计算奖励的函数
       batch_size = target.size(0)
       _, predicted = torch.max(output.data, 1)
       return (predicted == target).sum().item() / batch_size

   def metrics_fn(output, target):
       # metrics 函数接收 output  target 并计算出 dict metrics
       return {"acc1": top1_accuracy(output, target)}

   from nni.algorithms.nas.pytorch import enas
   trainer = enas.EnasTrainer(model,
                              loss=criterion,
                              metrics=metrics_fn,
                              reward_function=top1_accuracy,
                              optimizer=optimizer,
                              batch_size=128
                              num_epochs=10,  # 10 epochs
                              dataset_train=dataset_train,
                              dataset_valid=dataset_valid,
                              log_frequency=10)  #  10s 打印一次 log
   trainer.train()  # training
   trainer.export(file="model_dir/final_architecture.json")  # 把最终的架构导出到文件

``model``  `具有用户定义搜索空间的模型 <./WriteSearchSpace.rst>`__ 然后需要准备搜索数据和模型评估指标。 要从定义的搜索空间中进行搜索,需要实例化 One-Shot 算法,即 Trainer(如,EnasTrainer)。 Trainer 会提供一些可以自定义的参数。 如,损失函数,指标函数,优化器以及数据集。 这些功能可满足大部分需求,NNI 会尽力让内置 Trainer 能够处理更多的模型、任务和数据集。

**注意** ,在使用 One-Shot NAS 算法时,不需要启动 NNI Experiment 不需要 ``nnictl`` ,可直接运行 Python 脚本(即:``train.py`` ),如:``python3 train.py`` 训练完成后,可通过 ``trainer.export()`` 导出找到的最好的模型。

kvartet's avatar
kvartet committed
51
NNI 中每个 Trainer 都用其对应的场景和用法。 一些 Trainer 假定任务是分类任务;一些 Trainer  "epoch" 有不同的定义(如:ENAS 的每个 Epoch  一些子步骤加上 Controller 的步骤)。 大部分 Trainer 不支持分布式训练:没有使用 ``DataParallel``  ``DistributedDataParallel`` 来包装模型。 如果通过试用,想要在定制的应用中使用 Trainer,可能需要 `自定义 Trainer <./Advanced.rst#extend-the-ability-of-one-shot-trainers>`__
kvartet's avatar
kvartet committed
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

此外,可以使用 NAS 可视化来显示 One-Shot NAS `请看细节。 <./Visualization.rst>`__

使用导出的架构重新训练
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

搜索阶段后,就该训练找到的架构了。 与很多开源 NAS 算法不同,它们为重新训练专门写了新的模型。 我们发现搜索模型和重新训练模型的过程非常相似,因而可直接将一样的模型代码用到最终模型上。 例如:

.. code-block:: python

   model = Net()
   apply_fixed_architecture(model, "model_dir/final_architecture.json")

 JSON 是从 Mutable 键值到 Choice 的映射。 Choice 可为:


* string: 根据名称来指定候选项。
* number: 根据索引来指定候选项。
* string 数组: 根据名称来指定候选项。
* number 数组: 根据索引来指定候选项。
* boolean 数组: 可直接选定多项的数组。

例如:

.. code-block:: json

   {
       "LayerChoice1": "conv5x5",
       "LayerChoice2": 6,
       "InputChoice3": ["layer1", "layer3"],
       "InputChoice4": [1, 2],
       "InputChoice5": [false, true, false, false, true]
   }

应用后,模型会被固定,并准备好进行最终训练。 该模型作为单独的模型来工作,未使用的参数和模块已被剪除。

也可参考 `DARTS <./DARTS.rst>`__ 的重新训练代码。