神经架构搜索算法

Katib中神经架构搜索算法的概述

本页面描述了Katib中神经架构搜索(NAS)算法的工作原理。

高效神经架构搜索 (ENAS)

该算法遵循Hieu Pham、Melody Y. Guan、Barret Zoph、Quoc V. Le和Jeff Dean提出的通过参数共享的高效神经架构搜索的思想(https://arxiv.org/abs/1802.03268)以及Barret Zoph和Quoc V. Le的使用强化学习的神经架构搜索https://arxiv.org/abs/1611.01578)。

该实现基于 《通过参数共享的高效神经架构搜索》 的GitHub和 Google对ENAS的实现。 它使用带有LSTM单元的递归神经网络作为控制器来生成神经架构候选。 并且这个控制器网络是通过策略梯度更新的。然而,目前不支持参数共享。

Katib 实现

Katib 以特定格式表示神经网络。如果层数 (n) = 12 并且可能的操作数量 (m) = 6,则架构的定义将如下所示:

[2]
[0 0]
[1 1 0]
[5 1 0 1]
[1 1 1 0 1]
[5 0 0 1 0 1]
[1 1 1 0 0 1 0]
[2 0 0 0 1 1 0 1]
[0 0 0 1 1 1 1 1 0]
[2 0 1 0 1 1 1 0 0 0]
[3 1 1 1 1 1 1 0 0 1 1]
[0 1 1 1 1 0 0 1 1 1 1 0]

有 n 行,第 ith 行有 i 个元素,并描述第 ith 层。请注意,层 0 是输入,不包含在此定义中。

在每一行,第一整数范围从 0 到 m-1,表示此层的操作。 从第二个位置开始,第 kth 整数是一个布尔值,表示 (k-2)th 层是否与此层有跳过连接。 (从 (k-1)th 层到 kth 层将始终存在连接)

GetSuggestion() 的输出

算法服务中GetSuggestion()的输出由两个部分组成: architecturenn_config

architecture 是神经架构定义的 JSON 字符串。格式如上所述。一个例子是:

[[27], [29, 0], [22, 1, 0], [13, 0, 0, 0], [26, 1, 1, 0, 0], [30, 1, 0, 1, 0, 0], [11, 0, 1, 1, 0, 1, 1], [9, 1, 0, 0, 1, 0, 0, 0]]

nn_config 是一个 json 字符串,用于详细描述层数、输入大小、输出大小以及每个操作索引所代表的内容。与上述架构对应的 nn_config 可以是:

{
    "num_layers": 8,
    "input_sizes": [32, 32, 3],
    "output_sizes": [10],
    "embedding": {
        "27": {
            "opt_id": 27,
            "opt_type": "convolution",
            "opt_params": {
                "filter_size": "7",
                "num_filter": "96",
                "stride": "2"
            }
        },
        "29": {
            "opt_id": 29,
            "opt_type": "convolution",
            "opt_params": {
                "filter_size": "7",
                "num_filter": "128",
                "stride": "2"
            }
        },
        "22": {
            "opt_id": 22,
            "opt_type": "convolution",
            "opt_params": {
                "filter_size": "7",
                "num_filter": "48",
                "stride": "1"
            }
        },
        "13": {
            "opt_id": 13,
            "opt_type": "convolution",
            "opt_params": {
                "filter_size": "5",
                "num_filter": "48",
                "stride": "2"
            }
        },
        "26": {
            "opt_id": 26,
            "opt_type": "convolution",
            "opt_params": {
                "filter_size": "7",
                "num_filter": "96",
                "stride": "1"
            }
        },
        "30": {
            "opt_id": 30,
            "opt_type": "reduction",
            "opt_params": {
                "reduction_type": "max_pooling",
                "pool_size": 2
            }
        },
        "11": {
            "opt_id": 11,
            "opt_type": "convolution",
            "opt_params": {
                "filter_size": "5",
                "num_filter": "32",
                "stride": "2"
            }
        },
        "9": {
            "opt_id": 9,
            "opt_type": "convolution",
            "opt_params": {
                "filter_size": "3",
                "num_filter": "128",
                "stride": "2"
            }
        }
    }
}

这个神经架构可以被可视化为:

Example of NAS network

以下项目可以在Katib中实现,以更好地支持ENAS:

  1. 添加“微型”模式,这意味着搜索一个神经元而不是整个神经网络。
  2. 添加对循环神经网络的支持,并为宾夕法尼亚树库任务构建一个训练容器。
  3. 添加参数共享,如果可能的话。
  4. 将LSTM.py中自定义的LSTM单元更改为 tf.nn.rnn_cell.LSTMCell
  5. 将建议检查点存储到PVC,以防止意外的enas服务pod重启
  6. RequestCount 添加到 API 中,以便建议可以清理已完成研究的信息。

可微分架构搜索 (DARTS)

该算法遵循了 Hanxiao Liu、Karen Simonyan 和 Yiming Yang 提出的 DARTS: 可微分架构搜索 的思路: https://arxiv.org/abs/1806.09055。实现基于 官方 GitHub 实现流行的代码库

该算法通过以可微分的方式对任务进行公式化,从而解决了架构搜索的可扩展性挑战。它基于搜索空间中的连续放松和梯度下降。它能够高效地设计用于图像分类(在CIFAR-10和ImageNet上)的高性能卷积架构和用于语言建模(在Penn Treebank和WikiText-2上)的递归架构。

Katib 实现

为了在当前的Katib功能中支持DARTS,实施按以下方式进行:

  1. DARTS Suggestion service 创建实验搜索空间中的一组原始操作。 例如:

    ['separable_convolution_3x3', 'dilated_convolution_3x3', 'dilated_convolution_5x5', 'avg_pooling_3x3', 'max_pooling_3x3', 'skip_connection']
    
  2. 建议将算法设置、层数和原语集合返回给Katib控制器

  3. Katib 控制器启动 DARTS 训练容器 并设置适当的参数和所有可能的操作。

  4. 训练容器运行DARTS算法。

  5. 指标收集器从训练容器日志中保存最佳基因型。

最佳基因型表示

最佳基因型是每个神经网络层的最佳单元。单元通过DARTS算法生成。 这是最佳基因型的一个例子:

Genotype(
  normal=[
      [('max_pooling_3x3',0),('max_pooling_3x3',1)],
      [('max_pooling_3x3',0),('max_pooling_3x3',1)],
      [('max_pooling_3x3',0),('dilated_convolution_3x3',3)],
      [('max_pooling_3x3',0),('max_pooling_3x3',1)]
    ],
    normal_concat=range(2,6),
  reduce=[
      [('dilated_convolution_5x5',1),('separable_convolution_3x3',0)],
      [('max_pooling_3x3',2),('dilated_convolution_5x5',1)],
      [('dilated_convolution_5x5',3),('dilated_convolution_5x5',2)],
      [('dilated_convolution_5x5',3),('dilated_convolution_5x5',4)]
    ],
    reduce_concat=range(2,6)
)

在这个例子中,你可以看到4个DARTS节点,索引为:2,3,4,5。

reduce 参数是位于总神经网络层的 1/3 和 2/3 的单元。它们代表减少单元,在这些单元中,所有与输入节点相邻的操作的步幅为二。

normal 参数是位于其他神经网络层的细胞。 它们代表正常细胞。

在CNN中,所有的reduce和普通中间节点被连接在一起,每个节点有2条边。

每个 normal 数组中的元素是具有 2 条边的节点。第一个元素是边上的操作,第二个元素是节点索引连接。请注意,索引 0 是 C_{k-2} 节点,索引 1 是 C_{k-1} 节点。

例如 [('max_pooling_3x3',0),('max_pooling_3x3',1)] 意味着 C_{k-2} 节点连接到第一个节点,使用 max_pooling_3x3 操作(滤波器大小为3的最大池化),而 C_{k-1} 节点连接到第一个节点,使用 max_pooling_3x3 操作。

reduce 数组按照 normal 数组的相同方式。

normal_concatreduce_concat 表示中间节点之间的连接。

目前,它仅支持在单个 GPU 上运行和二阶近似,这比一阶产生了更好的结果。

以下项目可以在 DARTS 中实现:

  • 支持多 GPU 训练。添加选择用于训练的 GPU 的功能。

  • 在Katib UI中支持DARTS。

  • 考虑更好的最优基因型的表示。

  • 为CNN添加更多数据集。目前,它仅支持CIFAR-10。

  • 除了CNN外,还支持RNN。

  • 支持微模式,这意味着搜索特定的神经网络单元。

反馈

此页面有帮助吗?