paddleslim.nas 提供的搜索空间:#
- 根据原本模型结构构造搜索空间:
1.1 MobileNetV2Space
1.2 MobileNetV1Space
1.3 ResNetSpace
- 根据相应模型的block构造搜索空间
2.1 MobileNetV1BlockSpace
2.2 MobileNetV2BlockSpace
2.3 ResNetBlockSpace
2.4 InceptionABlockSpace
2.5 InceptionCBlockSpace
搜索空间的配置介绍:#
input_size(int|None):input_size
表示输入feature map的大小。
output_size(int|None):output_size
表示输出feature map的大小。
block_num(int|None):block_num
表示搜索空间中block的数量。
block_mask(list|None):block_mask
表示当前的block是一个reduction block还是一个normal block,是一组由0、1组成的列表,0表示当前block是normal block,1表示当前block是reduction block。如果设置了block_mask
,则主要以block_mask
为主要配置,input_size
,output_size
和block_num
三种配置是无效的。
Note:
1. reduction block表示经过这个block之后的feature map大小下降为之前的一半,normal block表示经过这个block之后feature map大小不变。
2. input_size
和output_size
用来计算整个模型结构中reduction block数量。
搜索空间示例:#
- 使用paddleslim中提供用原本的模型结构来构造搜索空间的话,仅需要指定搜索空间名字即可。例如:如果使用原本的MobileNetV2的搜索空间进行搜索的话,传入SANAS中的config直接指定为[('MobileNetV2Space')]。
- 使用paddleslim中提供的block搜索空间构造搜索空间:
2.1 使用
input_size
,output_size
和block_num
来构造搜索空间。例如:传入SANAS的config可以指定为[('MobileNetV2BlockSpace', {'input_size': 224, 'output_size': 32, 'block_num': 10})]。 2.2 使用block_mask
构造搜索空间。例如:传入SANAS的config可以指定为[('MobileNetV2BlockSpace', {'block_mask': [0, 1, 1, 1, 1, 0, 1, 0]})]。
自定义搜索空间(search space)#
自定义搜索空间类需要继承搜索空间基类并重写以下几部分:
1. 初始化的tokens(init_tokens
函数),可以设置为自己想要的tokens列表, tokens列表中的每个数字指的是当前数字在相应的搜索列表中的索引。例如本示例中若tokens=[0, 3, 5],则代表当前模型结构搜索到的通道数为[8, 40, 128]。
2. token中每个数字的搜索列表长度(range_table
函数),tokens中每个token的索引范围。
3. 根据token产生模型结构(token2arch
函数),根据搜索到的tokens列表产生模型结构。
以新增reset block为例说明如何构造自己的search space。自定义的search space不能和已有的search space同名。
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 51 52 53 54 55 56 57 58 59 60 61 | ### 引入搜索空间基类函数和search space的注册类函数 from .search_space_base import SearchSpaceBase from .search_space_registry import SEARCHSPACE import numpy as np ### 需要调用注册函数把自定义搜索空间注册到space space中 @SEARCHSPACE.register ### 定义一个继承SearchSpaceBase基类的搜索空间的类函数 class ResNetBlockSpace2(SearchSpaceBase): def __init__(self, input_size, output_size, block_num, block_mask): ### 定义一些实际想要搜索的内容,例如:通道数、每个卷积的重复次数、卷积核大小等等 ### self.filter_num 代表通道数的搜索列表 self.filter_num = np.array([8, 16, 32, 40, 64, 128, 256, 512]) ### 定义初始化token,初始化token的长度根据传入的block_num或者block_mask的长度来得到的 def init_tokens(self): return [0] * 3 * len(self.block_mask) ### 定义 def range_table(self): return [len(self.filter_num)] * 3 * len(self.block_mask) def token2arch(self, tokens=None): if tokens == None: tokens = self.init_tokens() self.bottleneck_params_list = [] for i in range(len(self.block_mask)): self.bottleneck_params_list.append(self.filter_num[tokens[i * 3 + 0]], self.filter_num[tokens[i * 3 + 1]], self.filter_num[tokens[i * 3 + 2]], 2 if self.block_mask[i] == 1 else 1) def net_arch(input): for i, layer_setting in enumerate(self.bottleneck_params_list): channel_num, stride = layer_setting[:-1], layer_setting[-1] input = self._resnet_block(input, channel_num, stride, name='resnet_layer{}'.format(i+1)) return input return net_arch ### 构造具体block的操作 def _resnet_block(self, input, channel_num, stride, name=None): shortcut_conv = self._shortcut(input, channel_num[2], stride, name=name) input = self._conv_bn_layer(input=input, num_filters=channel_num[0], filter_size=1, act='relu', name=name + '_conv0') input = self._conv_bn_layer(input=input, num_filters=channel_num[1], filter_size=3, stride=stride, act='relu', name=name + '_conv1') input = self._conv_bn_layer(input=input, num_filters=channel_num[2], filter_size=1, name=name + '_conv2') return fluid.layers.elementwise_add(x=shortcut_conv, y=input, axis=0, name=name+'_elementwise_add') def _shortcut(self, input, channel_num, stride, name=None): channel_in = input.shape[1] if channel_in != channel_num or stride != 1: return self.conv_bn_layer(input, num_filters=channel_num, filter_size=1, stride=stride, name=name+'_shortcut') else: return input def _conv_bn_layer(self, input, num_filters, filter_size, stride=1, padding='SAME', act=None, name=None): conv = fluid.layers.conv2d(input, num_filters, filter_size, stride, name=name+'_conv') bn = fluid.layers.batch_norm(conv, act=act, name=name+'_bn') return bn |