From e598cb9c0431202b5859c14e98149c13af47ab99 Mon Sep 17 00:00:00 2001 From: ceci3 <592712189@qq.com> Date: Thu, 5 Dec 2019 05:11:13 +0000 Subject: [PATCH] add inception --- .../nas/search_space/inception_block.py | 258 ++++++++++++------ 1 file changed, 172 insertions(+), 86 deletions(-) diff --git a/paddleslim/nas/search_space/inception_block.py b/paddleslim/nas/search_space/inception_block.py index 7c29be9c..34778f1b 100644 --- a/paddleslim/nas/search_space/inception_block.py +++ b/paddleslim/nas/search_space/inception_block.py @@ -23,10 +23,9 @@ from .search_space_base import SearchSpaceBase from .base_layer import conv_bn_layer from .search_space_registry import SEARCHSPACE -__all__ = [ - "InceptionABlockSpace", "InceptionBBlockSpace", "InceptionCBlockSpace" -] +__all__ = ["InceptionABlockSpace", "InceptionCBlockSpace"] ### TODO add asymmetric kernel of conv when paddle-lite support +### inceptionB is same as inceptionA if asymmetric kernel is not support @SEARCHSPACE.register @@ -45,7 +44,7 @@ class InceptionABlockSpace(SearchSpaceBase): ### self.filter_num means filter nums self.filter_num = np.array([ 3, 4, 8, 12, 16, 24, 32, 48, 64, 80, 96, 128, 144, 160, 192, 224, - 256, 320, 384, 480, 512, 1024 + 256, 320, 384, 448, 480, 512, 1024 ]) ### self.k_size means kernel_size self.k_size = np.array([3, 5]) @@ -161,7 +160,7 @@ class InceptionABlockSpace(SearchSpaceBase): input = self._inceptionA( input, - layer_setting[0:7], + A_tokens=filter_nums, filter_size=filter_size, stride=stride, pool_type=pool_type, @@ -244,97 +243,184 @@ class InceptionABlockSpace(SearchSpaceBase): [conv1, conv2, conv3, conv4], axis=1, name=name + '_concat') return concat - def _inceptionB(self, - data, - B_tokens=[0] * 7, - filter_size, - stride, - repeat, - name=None): - pool1 = fluid.layers.pool2d( - input=data, - pool_size=filter_size, - pool_padding='SAME', - pool_type='avg', - name=name + '_inceptionB_pool2d') - conv1 = conv_bn_layer( - input=pool1, - filter_size=1, - num_filters=B_tokens[0], - stride=stride, - act='relu', - name=name + '_inceptionB_conv1') - conv2 = conv_bn_layer( - input=data, - filter_size=1, - num_filters=B_tokens[1], - stride=stride, - act='relu', - name=name + '_inceptionB_conv2') +@SEARCHSPACE.register +class InceptionCBlockSpace(SearchSpaceBase): + def __init__(self, input_size, output_size, block_num, block_mask): + super(InceptionABlockSpace, self).__init__(input_size, output_size, + block_num, block_mask) + if self.block_mask == None: + # use input_size and output_size to compute self.downsample_num + self.downsample_num = compute_downsample_num(self.input_size, + self.output_size) + if self.block_num != None: + assert self.downsample_num <= self.block_num, 'downsample numeber must be LESS THAN OR EQUAL TO block_num, but NOW: downsample numeber is {}, block_num is {}'.format( + self.downsample_num, self.block_num) - conv3 = conv_bn_layer( - input=data, - filter_size=1, - num_filters=B_tokens[2], - stride=1, - act='relu', - name=name + '_inceptionB_conv3_1') - conv3 = conv_bn_layer( - input=conv3, - filter_size=filter_size, - num_filters=B_tokens[3], - stride=stride, - act='relu', - name=name + '_inceptionB_conv3_2') + ### self.filter_num means filter nums + self.filter_num = np.array([ + 3, 4, 8, 12, 16, 24, 32, 48, 64, 80, 96, 128, 144, 160, 192, 224, + 256, 320, 384, 448, 480, 512, 1024 + ]) + ### self.k_size means kernel_size + self.k_size = np.array([3, 5]) + ### self.pool_type means pool type, 0 means avg, 1 means max + self.pool_type = np.array([0, 1]) + ### self.repeat means repeat of 1x1 conv in branch of inception + ### self.repeat = np.array([0,1]) - conv4 = conv_bn_layer( - input=data, - filter_size=1, - num_filters=B_tokens[4], - stride=1, - act='relu', - name=name + '_inceptionB_conv4_1') - conv4 = conv_bn_layer( - input=conv4, - filter_size=filter_size, - num_filters=B_tokens[5], - stride=1, - act='relu', - name=name + '_inceptionB_conv4_2') - conv4 = conv_bn_layer( - input=conv4, - filter_size=filter_size, - num_filters=B_tokens[6], - stride=stride, - act='relu', - name=name + '_inceptionB_conv4_3') - concat = fluid.layers.concat( - [conv1, conv2, conv3, conv4], - axis=1, - name=name + '_inceptionB_concat') - return concat + def init_tokens(self): + """ + The initial token. + """ + if self.block_mask != None: + return [0] * (len(self.block_mask) * 9) + else: + return [0] * (self.block_num * 9) + + def range_table(self): + """ + Get range table of current search space, constrains the range of tokens. + """ + range_table_base = [] + if self.block_mask != None: + range_table_length = len(self.block_mask) + else: + range_table_length = self.block_mum + + for i in range(range_table_length): + range_table_base.append(len(self.filter_num)) + range_table_base.append(len(self.filter_num)) + range_table_base.append(len(self.filter_num)) + range_table_base.append(len(self.filter_num)) + range_table_base.append(len(self.filter_num)) + range_table_base.append(len(self.filter_num)) + range_table_base.append(len(self.filter_num)) + range_table_base.append(len(self.k_size)) + range_table_base.append(len(self.pooltype)) + + return range_table_base + + def token2arch(self, tokens=None): + """ + return net_arch function + """ + #assert self.block_num + if tokens is None: + tokens = self.init_tokens() + + self.bottleneck_params_list = [] + if self.block_mask != None: + for i in range(len(self.block_mask)): + self.bottleneck_params_list.append( + (self.filter_num[i * 11], self.filter_num[i * 11 + 1], + self.filter_num[i * 11 + 2], self.filter_num[i * 11 + 3], + self.filter_num[i * 11 + 4], self.filter_num[i * 11 + 5], + self.filter_num[i * 11 + 6], self.filter_num[i * 11 + 7], + self.filter_num[i * 11 + 8], self.k_size[i * 11 + 9], 2 if + self.block_mask == 1 else 1, self.pool_type[i * 11 + 10])) + else: + repeat_num = self.block_num / self.downsample_num + num_minus = self.block_num % self.downsample_num + ### if block_num > downsample_num, add stride=1 block at last (block_num-downsample_num) layers + for i in range(self.downsample_num): + self.bottleneck_params_list.append( + (self.filter_num[i * 11], self.filter_num[i * 11 + 1], + self.filter_num[i * 11 + 2], self.filter_num[i * 11 + 3], + self.filter_num[i * 11 + 4], self.filter_num[i * 11 + 5], + self.filter_num[i * 11 + 6], self.filter_num[i * 11 + 7], + self.filter_num[i * 11 + 8], self.k_size[i * 11 + 9], 2, + self.pool_type[i * 11 + 10])) + ### if block_num / downsample_num > 1, add (block_num / downsample_num) times stride=1 block + for k in range(repeat_num - 1): + kk = k * self.downsample_num + i + self.bottleneck_params_list.append(( + self.filter_num[kk * 11], self.filter_num[kk * 11 + 1], + self.filter_num[kk * 11 + 2], + self.filter_num[kk * 11 + 3], + self.filter_num[kk * 11 + 4], + self.filter_num[kk * 11 + 5], + self.filter_num[kk * 11 + 6], + self.filter_num[kk * 11 + 7], + self.filter_num[kk * 11 + 8], self.k_size[kk * 11 + 9], + 1, self.pool_type[kk * 11 + 10])) + + if self.downsample_num - i <= num_minus: + j = self.downsample_num * repeat_num + i + self.bottleneck_params_list.append( + (self.filter_num[j * 11], self.filter_num[j * 11 + 1], + self.filter_num[j * 11 + 2], + self.filter_num[j * 11 + 3], + self.filter_num[j * 11 + 4], + self.filter_num[j * 11 + 5], + self.filter_num[j * 11 + 6], + self.filter_num[j * 11 + 7], + self.filter_num[j * 11 + 8], self.k_size[j * 11 + 9], + 1, self.pool_type[j * 11 + 10])) + + if self.downsample_num == 0 and self.block_num != 0: + for i in range(len(self.block_num)): + self.bottleneck_params_list.append( + (self.filter_num[i * 11], self.filter_num[i * 11 + 1], + self.filter_num[i * 11 + 2], + self.filter_num[i * 11 + 3], + self.filter_num[i * 11 + 4], + self.filter_num[i * 11 + 5], + self.filter_num[i * 11 + 6], + self.filter_num[i * 11 + 7], + self.filter_num[i * 11 + 8], self.k_size[i * 11 + 9], + 1, self.pool_type[i * 11 + 10])) + + def net_arch(input, return_mid_layer=False, return_block=[]): + assert isinstance(return_block, + list), 'return_block must be a list.' + layer_count = 0 + mid_layer = dict() + for i, layer_setting in enumerate(self.bottleneck_params_list): + filter_nums = layer_setting[0:9] + filter_size = layer_setting[9] + stride = layer_setting[10] + pool_type = 'avg' if layer_setting[11] == 0 else 'max' + if stride == 2: + layer_count += 1 + if (layer_count - 1) in return_block: + mid_layer[layer_count - 1] = input + + input = self._inceptionC( + input, + C_tokens=filter_nums, + filter_size=filter_size, + stride=stride, + pool_type=pool_type, + name='inceptionC_{}'.format(i + 1)) + + if return_mid_layer: + return input, mid_layer + else: + return input + + return net_arch def _inceptionC(self, data, - C_tokens=[0] * 9, + C_tokens, filter_size, stride, - repeat, + pool_type, name=None): pool1 = fluid.layers.pool2d( input=data, pool_size=filter_size, pool_padding='SAME', - pool_type='avg', - name=name + '_inceptionC_pool2d') + pool_type=pool_type, + name=name + '_pool2d') conv1 = conv_bn_layer( input=pool1, filter_size=1, num_filters=C_tokens[0], stride=stride, act='relu', - name=name + '_inceptionC_conv1') + name=name + '_conv1') conv2 = conv_bn_layer( input=data, @@ -342,7 +428,7 @@ class InceptionABlockSpace(SearchSpaceBase): num_filters=C_tokens[1], stride=stride, act='relu', - name=name + '_inceptionC_conv2') + name=name + '_conv2') conv3 = conv_bn_layer( input=data, @@ -350,21 +436,21 @@ class InceptionABlockSpace(SearchSpaceBase): num_filters=C_tokens[2], stride=1, act='relu', - name=name + '_inceptionC_conv3_1') + name=name + '_conv3_1') conv3_1 = conv_bn_layer( input=conv3, filter_size=filter_size, num_filters=C_tokens[3], stride=stride, act='relu', - name=name + '_inceptionC_conv3_2_1') + name=name + '_conv3_2_1') conv3_2 = conv_bn_layer( input=conv3, filter_size=filter_size, num_filters=C_tokens[4], stride=stride, act='relu', - name=name + '_inceptionC_conv3_2_2') + name=name + '_conv3_2_2') conv4 = conv_bn_layer( input=data, @@ -372,31 +458,31 @@ class InceptionABlockSpace(SearchSpaceBase): num_filters=C_tokens[5], stride=1, act='relu', - name=name + '_inceptionC_conv4_1') + name=name + '_conv4_1') conv4 = conv_bn_layer( input=conv4, filter_size=filter_size, num_filters=C_tokens[6], stride=1, act='relu', - name=name + '_inceptionC_conv4_2') + name=name + '_conv4_2') conv4_1 = conv_bn_layer( input=conv4, filter_size=filter_size, num_filters=C_tokens[7], stride=stride, act='relu', - name=name + '_inceptionC_conv4_3_1') + name=name + '_conv4_3_1') conv4_2 = conv_bn_layer( input=conv4, filter_size=filter_size, num_filters=C_tokens[8], stride=stride, act='relu', - name=name + '_inceptionC_conv4_3_2') + name=name + '_conv4_3_2') concat = fluid.layers.concat( [conv1, conv2, conv3_1, conv3_2, conv4_1, conv4_2], axis=1, - name=name + '_inceptionC_concat') + name=name + '_concat') return concat -- GitLab