WriteSearchSpace.rst 3.85 KB
Newer Older
kvartet's avatar
kvartet committed
1
编写搜索空间
kvartet's avatar
kvartet committed
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
51
52
53
54
55
56
57
58
59
60
====================

通常,搜索空间是要在其中找到最好结构的候选项。 无论是经典 NAS 还是 One-Shot NAS,不同的搜索算法都需要搜索空间。 NNI 提供了统一的 API 来表达神经网络架构的搜索空间。

搜索空间可基于基础模型来构造。 这也是在已有模型上使用 NAS 的常用方法。 `MNIST on PyTorch <https://github.com/pytorch/examples/blob/master/mnist/main.py>`__ 是一个例子。 注意,NNI 为 PyTorch 和 TensorFlow 提供了同样的搜索空间 API。

.. code-block:: python

   from nni.nas.pytorch import mutables

   class Net(nn.Module):
       def __init__(self):
           super(Net, self).__init__()
           self.conv1 = mutables.LayerChoice([
               nn.Conv2d(1, 32, 3, 1),
               nn.Conv2d(1, 32, 5, 3)
           ])  # try 3x3 kernel and 5x5 kernel
           self.conv2 = nn.Conv2d(32, 64, 3, 1)
           self.dropout1 = nn.Dropout2d(0.25)
           self.dropout2 = nn.Dropout2d(0.5)
           self.fc1 = nn.Linear(9216, 128)
           self.fc2 = nn.Linear(128, 10)

       def forward(self, x):
           x = self.conv1(x)
           x = F.relu(x)
           # ... same as original ...
           return output

以上示例在 conv1 上添加了 conv5x5 的选项。 修改非常简单,只需要声明 ``LayerChoice`` 并将原始的 conv3x3 和新的 conv5x5 作为参数即可。 就这么简单! 不需要修改 forward 函数。 可将 conv1 想象为没有 NAS 的模型。

如何表示可能的连接? 通过 ``InputChoice`` 来实现。 要在 MNIST 示例上使用跳过连接,需要增加另一层 conv3。 下面的示例中,从 conv2 的可能连接加入到了 conv3 的输出中。

.. code-block:: python

   from nni.nas.pytorch import mutables

   class Net(nn.Module):
       def __init__(self):
           # ... same ...
           self.conv2 = nn.Conv2d(32, 64, 3, 1)
           self.conv3 = nn.Conv2d(64, 64, 1, 1)
           # declaring that there is exactly one candidate to choose from
           # search strategy will choose one or None
           self.skipcon = mutables.InputChoice(n_candidates=1)
           # ... same ...

       def forward(self, x):
           x = self.conv1(x)
           x = F.relu(x)
           x = self.conv2(x)
           x0 = self.skipcon([x])  # choose one or none from [x]
           x = self.conv3(x)
           if x0 is not None:  # skipconnection is open
               x += x0
           x = F.max_pool2d(x, 2)
           # ... same ...
           return output

kvartet's avatar
kvartet committed
61
Input Choice 可被视为可调用的模块,它接收张量数组,输出其中部分的连接、求和、平均(默认为求和),或没有选择时输出 ``None``。 就像 layer choices, input choices,应该用 ``__init__`` 来初始化,用 ``forward`` 来回调。 这会让搜索算法找到这些 Choice,并进行所需的准备。
kvartet's avatar
kvartet committed
62
63
64
65
66

``LayerChoice`` and ``InputChoice`` 都是 **mutables**。 Mutable 表示 "可变化的"。 与传统深度学习层、模型都是固定的不同,使用 Mutable 的模块,是一组可能选择的模型。

用户可以为每一个 mutable 声明一个 key。 默认情况下,NNI 会分配全局唯一的,但如果需要共享 Choice(例如,两个 ``LayerChoice`` 有同样的候选操作,希望共享同样的 Choice。即,如果一个选择了第 i 个操作,第二个也要选择第 i 个操作),那么就应该给它们相同的 key。 key 标记了此 Choice,并会在存储的检查点中使用。 如果要增加导出架构的可读性,可为每个 Mutable 的 key 指派名称。 mutables 的高级用法请参照文档 `Mutables <./NasReference.rst>`__。

kvartet's avatar
kvartet committed
67
定义了搜索空间后,下一步是从中找到最好的模型。 至于如何从定义的搜索空间进行搜索请参阅 `经典 NAS 算法 <./ClassicNas.rst>`__ 和 `one-shot NAS 算法 <./NasGuide.rst>`__ 。