Пример #1
0
    def test_model23(self):
        model1 = Sequential(self.s, model_table='Simple_CNN1')
        model1.add(InputLayer(3, 224, 224))
        model1.add(Conv2d(8, 7, act='identity', include_bias=False))
        model1.add(BN(act='relu'))
        model1.add(Pooling(2))
        model1.add(Conv2d(8, 7, act='identity', include_bias=False))
        model1.add(BN(act='relu'))
        model1.add(Pooling(2))
        model1.add(Dense(2))
        model1.add(OutputLayer(act='softmax', n=2))

        if self.data_dir is None:
            unittest.TestCase.skipTest(self, "DLPY_DATA_DIR is not set in the environment variables")

        caslib, path = caslibify(self.s, path=self.data_dir+'images.sashdat', task='load')

        self.s.table.loadtable(caslib=caslib,
                               casout={'name': 'eee', 'replace': True},
                               path=path)

        r = model1.fit(data='eee', inputs='_image_', target='_label_', max_epochs=1)
        self.assertTrue(r.severity == 0)

        model1.deploy(self.data_dir, output_format='onnx')
Пример #2
0
    def test_model13(self):
        # test dropout
        try:
            import onnx
        except:
            unittest.TestCase.skipTest(self, "onnx not found in the libraries")

        model1 = Sequential(self.s, model_table='Simple_CNN1')
        model1.add(InputLayer(3, 224, 224))
        model1.add(
            Conv2d(8, 7, act='IDENTITY', dropout=0.5, include_bias=False))
        model1.add(BN(act='relu'))
        model1.add(Pooling(2, pool='MEAN', dropout=0.5))
        model1.add(
            Conv2d(8, 7, act='IDENTITY', dropout=0.5, include_bias=False))
        model1.add(BN(act='relu'))
        model1.add(Pooling(2, pool='MEAN', dropout=0.5))
        model1.add(Conv2d(8, 7, act='identity', include_bias=False))
        model1.add(BN(act='relu'))
        model1.add(Dense(16, act='IDENTITY', dropout=0.1))
        model1.add(OutputLayer(act='softmax', n=2))

        if self.data_dir is None:
            unittest.TestCase.skipTest(
                self, "DLPY_DATA_DIR is not set in the environment variables")

        caslib, path, tmp_caslib = caslibify(self.s,
                                             path=self.data_dir +
                                             'images.sashdat',
                                             task='load')

        self.s.table.loadtable(caslib=caslib,
                               casout={
                                   'name': 'eee',
                                   'replace': True
                               },
                               path=path)

        r = model1.fit(data='eee',
                       inputs='_image_',
                       target='_label_',
                       max_epochs=2)
        self.assertTrue(r.severity == 0)

        import tempfile
        tmp_dir_to_dump = tempfile.gettempdir()
        model1.deploy(tmp_dir_to_dump, output_format='onnx')

        import os
        os.remove(os.path.join(tmp_dir_to_dump, "Simple_CNN1.onnx"))

        if (caslib is not None) and tmp_caslib:
            self.s.retrieve('table.dropcaslib',
                            message_level='error',
                            caslib=caslib)
Пример #3
0
def downsampling_bottleneck(x, in_depth, out_depth, projection_ratio=4):
    '''
    Defines the down-sampling bottleneck of ENet

    Parameters
    ----------
    x : class:`Layer'
        Previous layer to this block
    in_depth : int
        Depth of the layer fed into this block
    out_depth : int
        Depth of the output layer of this block
    projection_ratio : int, optional
        Used to calculate the reduced_depth for intermediate convolution layers
        Default: 4

    Returns
    -------
    :class:`Res`
    '''

    reduced_depth = int(in_depth // projection_ratio)

    conv1 = Conv2d(reduced_depth,
                   3,
                   stride=2,
                   padding=1,
                   act='identity',
                   include_bias=False)(x)
    bn1 = BN(act='relu')(conv1)

    conv2 = Conv2d(reduced_depth,
                   3,
                   stride=1,
                   act='identity',
                   include_bias=False)(bn1)
    bn2 = BN(act='relu')(conv2)

    conv3 = Conv2d(out_depth, 1, stride=1, act='identity',
                   include_bias=False)(bn2)
    bn3 = BN(act='relu')(conv3)

    pool1 = Pooling(2, stride=2)(x)
    conv4 = Conv2d(out_depth, 1, stride=1, act='identity',
                   include_bias=False)(pool1)
    bn4 = BN(act='relu')(conv4)

    res = Res()([bn3, bn4])

    return res
Пример #4
0
    def _depthwise_conv_block(inputs,
                              n_groups,
                              pointwise_conv_filters,
                              alpha,
                              depth_multiplier=1,
                              stride=1,
                              block_id=1):
        """Adds a depthwise convolution block.

        inputs:
            Input tensor
        n_groups : int
            number of groups
        pointwise_conv_filters:
            the dimensionality of the output space
        alpha: controls the width of the network.
            - If `alpha` < 1.0, proportionally decreases the number
                of filters in each layer.
            - If `alpha` > 1.0, proportionally increases the number
                of filters in each layer.
            - If `alpha` = 1, default number of filters from the paper
                 are used at each layer.
        depth_multiplier:
            The number of depthwise convolution output channels
        strides: An integer or tuple/list of 2 integers,
            specifying the strides of the convolution
        block_id: Integer, a unique identification designating
            the block number.

        """
        pointwise_conv_filters = int(pointwise_conv_filters * alpha)

        x = GroupConv2d(n_groups * depth_multiplier,
                        n_groups,
                        3,
                        stride=stride,
                        act='identity',
                        include_bias=False,
                        name='conv_dw_%d' % block_id)(inputs)
        x = BN(name='conv_dw_%d_bn' % block_id, act='relu')(x)

        x = Conv2d(pointwise_conv_filters,
                   1,
                   act='identity',
                   include_bias=False,
                   stride=1,
                   name='conv_pw_%d' % block_id)(x)
        x = BN(name='conv_pw_%d_bn' % block_id, act='relu')(x)
        return x, pointwise_conv_filters
Пример #5
0
    def _conv_block(inputs, filters, alpha, kernel=3, stride=1):
        """
        Adds an initial convolution layer (with batch normalization

        inputs:
            Input tensor
        filters:
            the dimensionality of the output space
        alpha: controls the width of the network.
            - If `alpha` < 1.0, proportionally decreases the number
                of filters in each layer.
            - If `alpha` > 1.0, proportionally increases the number
                of filters in each layer.
            - If `alpha` = 1, default number of filters from the paper
                 are used at each layer.
        kernel:
            specifying the width and height of the 2D convolution window.
        strides:
            the strides of the convolution

        """
        filters = int(filters * alpha)
        x = Conv2d(filters,
                   kernel,
                   act='identity',
                   include_bias=False,
                   stride=stride,
                   name='conv1')(inputs)
        x = BN(name='conv1_bn', act='relu')(x)
        return x, filters
Пример #6
0
def onnx_extract_batchnormalization(graph, node, layers):
    ''' 
    Construct batchnorm layer from ONNX op 
    
    Parameters
    ----------
    graph : ONNX GraphProto
        Specifies a GraphProto object.
    node : ONNX NodeProto
        Specifies a NodeProto object.
    layers : list of Layers
        Specifies the existing layers of a model.
    
    Returns
    -------
    :class:`BN`

    '''
    previous = onnx_find_previous_compute_layer(graph, node)

    if not previous:
        src_names = [find_input_layer_name(graph)]
    else:
        src_names = [p.name for p in previous]

    src = [get_dlpy_layer(layers, i) for i in src_names]

    return BN(name=node.name, act='identity', src_layers=src)
Пример #7
0
def upsampling_bottleneck(x, in_depth, out_depth, projection_ratio=4):
    '''
    Defines the up-sampling bottleneck of ENet

    Parameters
    ----------
    x : class:`Layer'
       Previous layer to this block
    in_depth : int
       Depth of the layer fed into this block
    out_depth : int
       Depth of the output layer of this block
    projection_ratio : int, optional
       Used to calculate the reduced_depth for intermediate convolution layers
       Default: 4

    Returns
    -------
    :class:`BN`
    '''

    reduced_depth = int(in_depth // projection_ratio)

    conv1 = Conv2d(reduced_depth,
                   1,
                   stride=1,
                   act='identity',
                   include_bias=False)(x)
    bn1 = BN(act='relu')(conv1)

    tconv1 = Conv2DTranspose(reduced_depth,
                             3,
                             stride=2,
                             padding=1,
                             output_padding=1,
                             act='identity',
                             include_bias=False)(bn1)
    bn2 = BN(act='relu')(tconv1)

    conv3 = Conv2d(out_depth, 1, stride=1, act='identity',
                   include_bias=False)(bn2)
    bn3 = BN(act='relu')(conv3)

    return bn3
Пример #8
0
    def test_model_crnn_bug(self):
        model = Sequential(self.s, model_table='crnn')
        model.add(InputLayer(3,256,16))
        model.add(Reshape(height=16,width=256,depth=3))

        model.add(Conv2d(64,3,3,stride=1,padding=1))                # size = 16x256x64
        model.add(Pooling(2,2,2))                                   # size = 8x128x64

        model.add(Conv2d(128,3,3,stride=1,padding=1))               # size = 8x128x128
        model.add(Pooling(2,2,2))                                   # size = 4x64x128

        model.add(Conv2d(256,3,3,stride=1,padding=1,act='IDENTITY')) # size = 4x64x256
        model.add(BN(act='RELU'))                   # size = 4x64x256

        model.add(Conv2d(256,3,3,stride=1,padding=1))              # size = 4x64x256


        model.add(Pooling(1,2,stride_horizontal=1, stride_vertical=2))



        #, padding=1))           #  size = 2x64x256
        #model.add(Pooling(1,2,stride=2,stride_horizontal=1, stride_vertical=2,))           # size = 2x64x256

        model.add(Conv2d(512,3,3,stride=1,padding=1, act='IDENTITY')) # size = 2x64x512
        model.add(BN(act='RELU'))

        model.add(Conv2d(512,3,3,stride=1,padding=1))              # size = 2x64x512
        model.add(Pooling(1,2,stride_horizontal=1, stride_vertical=2)) #, padding=1))           # size = 1x64x512
        #model.add(Pooling(1,2,stride=2,stride_horizontal=1, stride_vertical=2,))           # size = 1x64x512

        model.add(Conv2d(512,3,3,stride=1,padding=1, act='IDENTITY')) # size = 1x64x512
        model.add(BN(act='RELU'))

        model.add(Reshape(order='DWH',width=64, height=512, depth=1))

        model.add(Recurrent(512,output_type='SAMELENGTH'))

        model.add(OutputLayer(error='CTC'))

        model.print_summary()
Пример #9
0
def initial_block(inp):
    '''
    Defines the initial block of ENet

    Parameters
    ----------
    inp : class:`InputLayer`
    Input layer

    Returns
    -------
    :class:`Concat`
    '''
    x = Conv2d(13, 3, stride=2, padding=1, act='identity',
               include_bias=False)(inp)
    x_bn = BN(act='relu')(x)
    y = Pooling(2)(inp)
    merge = Concat()([x_bn, y])

    return merge
Пример #10
0
 def test_bn_layer2(self):
     if not __dev__:
         with self.assertRaises(DLPyError):
             BN(not_a_parameter=1)
Пример #11
0
 def test_bn_layer1(self):
     dict1 = BN(name='bn',
                src_layers=[Conv2d(name='conv',
                                   n_filters=32)]).to_model_params()
     self.assertTrue(self.sample_syntax['bn1'] == dict1)
Пример #12
0
def VGG13(conn,
          model_table='VGG13',
          n_classes=1000,
          n_channels=3,
          width=224,
          height=224,
          scale=1,
          random_flip=None,
          random_crop=None,
          offsets=(103.939, 116.779, 123.68),
          random_mutation=None):
    '''
    Generates a deep learning model with the VGG13 architecture.

    Parameters
    ----------
    conn : CAS
        Specifies the CAS connection object.
    model_table : string, optional
        Specifies the name of CAS table to store the model.
    n_classes : int, optional
        Specifies the number of classes. If None is assigned, the model will
        automatically detect the number of classes based on the training set.
        Default: 1000
    n_channels : int, optional
        Specifies the number of the channels (i.e., depth) of the input layer.
        Default: 3
    width : int, optional
        Specifies the width of the input layer.
        Default: 224
    height : int, optional
        Specifies the height of the input layer.
        Default: 224
    scale : double, optional
        Specifies a scaling factor to be applied to each pixel intensity values.
        Default: 1
    random_flip : string, optional
        Specifies how to flip the data in the input layer when image data is
        used. Approximately half of the input data is subject to flipping.
        Valid Values: 'h', 'hv', 'v', 'none'
    random_crop : string, optional
        Specifies how to crop the data in the input layer when image data is
        used. Images are cropped to the values that are specified in the width
        and height parameters. Only the images with one or both dimensions
        that are larger than those sizes are cropped.
        Valid Values: 'none', 'unique', 'randomresized', 'resizethencrop'
    offsets : double or iter-of-doubles, optional
        Specifies an offset for each channel in the input data. The final input
        data is set after applying scaling and subtracting the specified offsets.
        Default: (103.939, 116.779, 123.68)
    random_mutation : string, optional
        Specifies how to apply data augmentations/mutations to the data in the input layer.
        Valid Values: 'none', 'random'

    Returns
    -------
    :class:`Sequential`

    References
    ----------
    https://arxiv.org/pdf/1409.1556.pdf

    '''
    conn.retrieve('loadactionset',
                  _messagelevel='error',
                  actionset='deeplearn')

    # get all the parms passed in
    parameters = locals()

    model = Sequential(conn=conn, model_table=model_table)

    # get the input parameters
    input_parameters = get_layer_options(input_layer_options, parameters)
    model.add(InputLayer(**input_parameters))

    model.add(
        Conv2d(n_filters=64,
               width=3,
               height=3,
               stride=1,
               act='identity',
               include_bias=False))
    model.add(BN(act='relu'))
    model.add(
        Conv2d(n_filters=64,
               width=3,
               height=3,
               stride=1,
               act='identity',
               include_bias=False))
    model.add(BN(act='relu'))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))

    model.add(
        Conv2d(n_filters=128,
               width=3,
               height=3,
               stride=1,
               act='identity',
               include_bias=False))
    model.add(BN(act='relu'))
    model.add(
        Conv2d(n_filters=128,
               width=3,
               height=3,
               stride=1,
               act='identity',
               include_bias=False))
    model.add(BN(act='relu'))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))

    model.add(
        Conv2d(n_filters=256,
               width=3,
               height=3,
               stride=1,
               act='identity',
               include_bias=False))
    model.add(BN(act='relu'))
    model.add(
        Conv2d(n_filters=256,
               width=3,
               height=3,
               stride=1,
               act='identity',
               include_bias=False))
    model.add(BN(act='relu'))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))

    model.add(
        Conv2d(n_filters=512,
               width=3,
               height=3,
               stride=1,
               act='identity',
               include_bias=False))
    model.add(BN(act='relu'))
    model.add(
        Conv2d(n_filters=512,
               width=3,
               height=3,
               stride=1,
               act='identity',
               include_bias=False))
    model.add(BN(act='relu'))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))

    model.add(
        Conv2d(n_filters=512,
               width=3,
               height=3,
               stride=1,
               act='identity',
               include_bias=False))
    model.add(BN(act='relu'))
    model.add(
        Conv2d(n_filters=512,
               width=3,
               height=3,
               stride=1,
               act='identity',
               include_bias=False))
    model.add(BN(act='relu'))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))

    model.add(Dense(n=4096, dropout=0.5))
    model.add(Dense(n=4096, dropout=0.5))

    model.add(OutputLayer(n=n_classes))

    return model
Пример #13
0
def EfficientNet(conn, model_table='EfficientNet', n_classes=100, n_channels=3, width=224, height=224,
                 width_coefficient=1, depth_coefficient=1, dropout_rate=0.2, drop_connect_rate=0, depth_divisor=8,
                 activation_fn='relu', blocks_args=_MBConv_BLOCKS_ARGS,
                 offsets=(255*0.406, 255*0.456, 255*0.485), norm_stds=(255*0.225, 255*0.224, 255*0.229),
                 random_flip=None, random_crop=None, random_mutation=None):
    '''
    Generates a deep learning model with the EfficientNet architecture.
    The implementation is revised based on
    https://github.com/keras-team/keras-applications/blob/master/keras_applications/efficientnet.py

    Parameters
    ----------
    conn : CAS
        Specifies the CAS connection object.
    model_table : string or dict or CAS table, optional
        Specifies the CAS table to store the deep learning model.
    n_classes : int, optional
        Specifies the number of classes. If None is assigned, the model will
        automatically detect the number of classes based on the training set.
        Default: 1000
    n_channels : int, optional
        Specifies the number of the channels (i.e., depth) of the input layer.
        Default: 3
    width : int, optional
        Specifies the width of the input layer.
        Default: 224
    height : int, optional
        Specifies the height of the input layer.
        Default: 224
    width_coefficient: double, optional
        Specifies the scale coefficient for network width.
        Default: 1.0
    depth_coefficient: double, optional
        Specifies the scale coefficient for network depth.
        Default: 1.0
    dropout_rate: double, optional
        Specifies the dropout rate before final classifier layer.
        Default: 0.2
    drop_connect_rate: double, optional
        Specifies the dropout rate at skip connections.
        Default: 0.0
    depth_divisor: integer, optional
        Specifies the unit of network width.
        Default: 8
    activation_fn: string, optional
        Specifies the activation function
    blocks_args: list of dicts
         Specifies parameters to construct blocks for the efficientnet model.
    offsets : double or iter-of-doubles, optional
        Specifies an offset for each channel in the input data. The final input
        data is set after applying scaling and subtracting the specified offsets.
        Default: (255*0.406, 255*0.456, 255*0.485)
    norm_stds : double or iter-of-doubles, optional
        Specifies a standard deviation for each channel in the input data.
        The final input data is normalized with specified means and standard deviations.
        Default: (255*0.225, 255*0.224, 255*0.229)
    random_flip : string, optional
        Specifies how to flip the data in the input layer when image data is
        used. Approximately half of the input data is subject to flipping.
        Valid Values: 'h', 'hv', 'v', 'none'
    random_crop : string, optional
        Specifies how to crop the data in the input layer when image data is
        used. Images are cropped to the values that are specified in the width
        and height parameters. Only the images with one or both dimensions
        that are larger than those sizes are cropped.
        Valid Values: 'none', 'unique', 'randomresized', 'resizethencrop'
    random_mutation : string, optional
        Specifies how to apply data augmentations/mutations to the data in the input layer.
        Valid Values: 'none', 'random'


    Returns
    -------
    :class:`Model`

    References
    ----------
    https://arxiv.org/pdf/1905.11946.pdf

    '''

    def round_filters(filters, width_coefficient, depth_divisor):
        '''
        round the number of the scaled width, which is for width scaling in efficientnet.
        Parameters
        ----------
        filters: integer
            Specifies the number of filters.
        width_coefficient: double
            Specifies the scale coefficient for network width.
        depth_divisor: integer
            Specifies the unit of network width.
        '''

        filters *= width_coefficient
        new_filters = int(filters + depth_divisor / 2) // depth_divisor * depth_divisor
        new_filters = max(depth_divisor, new_filters)
        # Make sure that round down does not go down by more than 10%.
        if new_filters < 0.9 * filters:
            new_filters += depth_divisor
        return int(new_filters)

    def round_repeats(repeats, depth_coefficient):
        '''
        round the number of the scaled depth, which is for depth scaling in effcientnet.
        Parameters
        ----------
        repeats: integer
            Specifies the number of repeats for a block.
        depth_coefficient: double
            Specifies the scale coefficient for a block.
        '''

        return int(math.ceil(depth_coefficient * repeats))

    def _MBConvBlock(inputs, in_channels, out_channels, ksize, stride, expansion, se_ratio, stage_id, block_id,
                     noskip=False, activation_fn='relu'):
        '''
        Inverted Residual Block

        Parameters
        ----------
        inputs: input tensor
            Speecify input tensor for block.
        in_channels: integer
            Specifies the number of input tensor's channel.
        out_channels: integer
            Specifies the number of output tensor's channel
        ksize:
            Specifies the kernel size of the convolution
        stride: integer
            Specifies the stride of the convolution
        expansion: double
            Specifies the expansion factor for the input layer.
        se_ratio: double
            Specifies the ratio to squeeze the input filters for squeeze-and-excitation block.
        stage_id: integer
            Specifies stage id for naming layers
        block_id:
            Specifies block id for naming layers
        noskip: bool
            Specifies whether the skip connection is used. By default, the skip connection is used.
        activation_fn:
            Specifies activation function
        '''

        # mobilenetv2 block is also known as inverted residual block, which consists of three convolutions:
        # the first is 1*1 convolution for expansion
        # the second is depthwise convolution
        # the third is 1*1 convolution without any non-linearity for projection

        x = inputs
        prefix = 'stage_{}_block_{}'.format(stage_id, block_id)
        n_groups = in_channels  # for expansion=1, n_groups might be different from pointwise_filters

        if expansion > 1:
            # For MobileNet V2, expansion>1 when stage>0
            n_groups = int(expansion * in_channels)  ## update n_groups
            x = Conv2d(n_groups, 1, include_bias=False, act='identity',
                       name=prefix + 'expand')(x)
            x = BN(name=prefix + 'expand_BN', act='identity')(x)

        # Depthwise convolution
        x = GroupConv2d(n_groups, n_groups, ksize, stride=stride, act='identity',
                        include_bias=False, name=prefix + 'depthwise')(x)
        x = BN(name=prefix + 'depthwise_BN', act=activation_fn)(x)

        # Squeeze-Excitation
        if 0 < se_ratio <= 1:
            se_input = x  # features to be squeezed
            x = GlobalAveragePooling2D(name=prefix + "global_avg_pool")(x)
            # Squeeze
            channels_se = max(1, int(in_channels * se_ratio))
            x = Conv2d(channels_se, 1, include_bias=True, act=activation_fn, name=prefix + 'squeeze')(x)
            x = Conv2d(n_groups, 1, include_bias=True, act='sigmoid', name=prefix + 'excitation')(x)
            x = Reshape(name=prefix + 'reshape', width=n_groups, height=1, depth=1)(x)
            x = Scale(name=prefix + 'scale')([se_input, x])  # x = out*w

        # Project
        x = Conv2d(out_channels, 1, include_bias=False, act='identity', name=prefix + 'project')(x)
        x = BN(name=prefix + 'project_BN', act='identity')(x)  # identity activation on narrow tensor
        # Prepare output for MBConv block
        if in_channels == out_channels and stride == 1 and (not noskip):
            # dropout can be added.
            return Res(name=prefix + 'add_se_residual')([x, inputs])
        else:
            return x

    parameters = locals()
    input_parameters = get_layer_options(input_layer_options, parameters)
    inp = Input(**input_parameters, name='data')
    # refer to Table 1  "EfficientNet-B0 baseline network" in paper:
    # "EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks"
    stage_id = 0
    out_channels = round_filters(32, width_coefficient,
                                 depth_divisor)  # multiply with width multiplier: width_coefficient
    x = Conv2d(out_channels, 3, stride=2, include_bias=False, name='Conv1', act='identity')(inp)
    x = BN(name='bn_Conv1', act=activation_fn)(x)

    # Create stages with MBConv blocks from stage 1
    in_channels = out_channels  # number of input channels for first MBblock
    stage_id +=1
    total_blocks = float(sum(args[2] for args in blocks_args))
    for expansion, out_channels, num_blocks, ksize, stride, se_ratio in blocks_args:
        out_channels = round_filters(out_channels, width_coefficient, depth_divisor)
        num_blocks = round_repeats(num_blocks, depth_coefficient)
        strides = [stride] + [1] * (num_blocks - 1)
        for block_id, stride in enumerate(strides):
            x = _MBConvBlock(x, in_channels, out_channels, ksize, stride, expansion, se_ratio, stage_id, block_id,activation_fn)
            in_channels = out_channels  # out_channel
        stage_id += 1

    last_block_filters = round_filters(1280, width_coefficient, depth_divisor)
    x = Conv2d(last_block_filters, 1, include_bias=False, name='Conv_top', act='identity')(x)
    x = BN(name='Conv_top_bn', act=activation_fn)(x)

    x = GlobalAveragePooling2D(name="Global_avg_pool", dropout=dropout_rate)(x)
    x = OutputLayer(n=n_classes)(x)

    model = Model(conn, inp, x, model_table)
    model.compile()
    return model
Пример #14
0
    def _MBConvBlock(inputs, in_channels, out_channels, ksize, stride, expansion, se_ratio, stage_id, block_id,
                     noskip=False, activation_fn='relu'):
        '''
        Inverted Residual Block

        Parameters
        ----------
        inputs: input tensor
            Speecify input tensor for block.
        in_channels: integer
            Specifies the number of input tensor's channel.
        out_channels: integer
            Specifies the number of output tensor's channel
        ksize:
            Specifies the kernel size of the convolution
        stride: integer
            Specifies the stride of the convolution
        expansion: double
            Specifies the expansion factor for the input layer.
        se_ratio: double
            Specifies the ratio to squeeze the input filters for squeeze-and-excitation block.
        stage_id: integer
            Specifies stage id for naming layers
        block_id:
            Specifies block id for naming layers
        noskip: bool
            Specifies whether the skip connection is used. By default, the skip connection is used.
        activation_fn:
            Specifies activation function
        '''

        # mobilenetv2 block is also known as inverted residual block, which consists of three convolutions:
        # the first is 1*1 convolution for expansion
        # the second is depthwise convolution
        # the third is 1*1 convolution without any non-linearity for projection

        x = inputs
        prefix = 'stage_{}_block_{}'.format(stage_id, block_id)
        n_groups = in_channels  # for expansion=1, n_groups might be different from pointwise_filters

        if expansion > 1:
            # For MobileNet V2, expansion>1 when stage>0
            n_groups = int(expansion * in_channels)  ## update n_groups
            x = Conv2d(n_groups, 1, include_bias=False, act='identity',
                       name=prefix + 'expand')(x)
            x = BN(name=prefix + 'expand_BN', act='identity')(x)

        # Depthwise convolution
        x = GroupConv2d(n_groups, n_groups, ksize, stride=stride, act='identity',
                        include_bias=False, name=prefix + 'depthwise')(x)
        x = BN(name=prefix + 'depthwise_BN', act=activation_fn)(x)

        # Squeeze-Excitation
        if 0 < se_ratio <= 1:
            se_input = x  # features to be squeezed
            x = GlobalAveragePooling2D(name=prefix + "global_avg_pool")(x)
            # Squeeze
            channels_se = max(1, int(in_channels * se_ratio))
            x = Conv2d(channels_se, 1, include_bias=True, act=activation_fn, name=prefix + 'squeeze')(x)
            x = Conv2d(n_groups, 1, include_bias=True, act='sigmoid', name=prefix + 'excitation')(x)
            x = Reshape(name=prefix + 'reshape', width=n_groups, height=1, depth=1)(x)
            x = Scale(name=prefix + 'scale')([se_input, x])  # x = out*w

        # Project
        x = Conv2d(out_channels, 1, include_bias=False, act='identity', name=prefix + 'project')(x)
        x = BN(name=prefix + 'project_BN', act='identity')(x)  # identity activation on narrow tensor
        # Prepare output for MBConv block
        if in_channels == out_channels and stride == 1 and (not noskip):
            # dropout can be added.
            return Res(name=prefix + 'add_se_residual')([x, inputs])
        else:
            return x
Пример #15
0
def UNet(conn,
         model_table='UNet',
         n_classes=2,
         n_channels=1,
         width=256,
         height=256,
         scale=1.0 / 255,
         norm_stds=None,
         offsets=None,
         random_mutation=None,
         init=None,
         bn_after_convolutions=False,
         random_flip=None,
         random_crop=None):
    '''
    Generates a deep learning model with the U-Net architecture.

    Parameters
    ----------
    conn : CAS
        Specifies the connection of the CAS connection.
    model_table : string, optional
        Specifies the name of CAS table to store the model.
    n_classes : int, optional
        Specifies the number of classes. If None is assigned, the model will
        automatically detect the number of classes based on the training set.
        Default: 2
    n_channels : int, optional
        Specifies the number of the channels (i.e., depth) of the input layer.
        Default: 3
    width : int, optional
        Specifies the width of the input layer.
        Default: 256
    height : int, optional
        Specifies the height of the input layer.
        Default: 256
    scale : double, optional
        Specifies a scaling factor to be applied to each pixel intensity values.
        Default: 1.0/255
    norm_stds : double or iter-of-doubles, optional
        Specifies a standard deviation for each channel in the input data.
        The final input data is normalized with specified means and standard deviations.
    offsets : double or iter-of-doubles, optional
        Specifies an offset for each channel in the input data. The final input
        data is set after applying scaling and subtracting the specified offsets.
    random_mutation : string, optional
        Specifies how to apply data augmentations/mutations to the data in the
        input layer.
        Valid Values: 'none', 'random'
    init : str
        Specifies the initialization scheme for convolution layers.
        Valid Values: XAVIER, UNIFORM, NORMAL, CAUCHY, XAVIER1, XAVIER2, MSRA, MSRA1, MSRA2
        Default: None
    bn_after_convolutions : Boolean
        If set to True, a batch normalization layer is added after each convolution layer.
    random_flip : string, optional
        Specifies how to flip the data in the input layer when image data is
        used. Approximately half of the input data is subject to flipping.
        Valid Values: 'h', 'hv', 'v', 'none'
    random_crop : string, optional
        Specifies how to crop the data in the input layer when image data is
        used. Images are cropped to the values that are specified in the width
        and height parameters. Only the images with one or both dimensions
        that are larger than those sizes are cropped.
        Valid Values: 'none', 'unique', 'randomresized', 'resizethencrop'

    Returns
    -------
    :class:`Sequential`

    References
    ----------
    https://arxiv.org/pdf/1505.04597

    '''
    parameters = locals()
    input_parameters = get_layer_options(input_layer_options, parameters)
    inp = Input(**input_parameters, name='data')
    act_conv = 'relu'
    bias_conv = True
    if bn_after_convolutions:
        act_conv = 'identity'
        bias_conv = False
    # The model follows UNet paper architecture. The network down-samples by performing max pooling with stride=2
    conv1 = Conv2d(64, 3, act=act_conv, init=init, include_bias=bias_conv)(inp)
    conv1 = BN(act='relu')(conv1) if bn_after_convolutions else conv1
    conv1 = Conv2d(64, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(conv1)
    conv1 = BN(act='relu')(conv1) if bn_after_convolutions else conv1
    pool1 = Pooling(2)(conv1)

    conv2 = Conv2d(128, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(pool1)
    conv2 = BN(act='relu')(conv2) if bn_after_convolutions else conv2
    conv2 = Conv2d(128, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(conv2)
    conv2 = BN(act='relu')(conv2) if bn_after_convolutions else conv2
    pool2 = Pooling(2)(conv2)

    conv3 = Conv2d(256, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(pool2)
    conv3 = BN(act='relu')(conv3) if bn_after_convolutions else conv3
    conv3 = Conv2d(256, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(conv3)
    conv3 = BN(act='relu')(conv3) if bn_after_convolutions else conv3
    pool3 = Pooling(2)(conv3)

    conv4 = Conv2d(512, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(pool3)
    conv4 = BN(act='relu')(conv4) if bn_after_convolutions else conv4
    conv4 = Conv2d(512, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(conv4)
    conv4 = BN(act='relu')(conv4) if bn_after_convolutions else conv4
    pool4 = Pooling(2)(conv4)

    conv5 = Conv2d(1024, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(pool4)
    conv5 = BN(act='relu')(conv5) if bn_after_convolutions else conv5
    conv5 = Conv2d(1024, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(conv5)
    conv5 = BN(act='relu')(conv5) if bn_after_convolutions else conv5
    # the minimum is 1/2^4 of the original image size
    # Our implementation applies Transpose convolution to upsample feature maps.
    tconv6 = Conv2DTranspose(512,
                             3,
                             stride=2,
                             act='relu',
                             padding=1,
                             output_size=conv4.shape,
                             init=init)(conv5)  # 64
    # concatenation layers to combine encoder and decoder features
    merge6 = Concat()([conv4, tconv6])
    conv6 = Conv2d(512, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(merge6)
    conv6 = BN(act='relu')(conv6) if bn_after_convolutions else conv6
    conv6 = Conv2d(512, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(conv6)
    conv6 = BN(act='relu')(conv6) if bn_after_convolutions else conv6

    tconv7 = Conv2DTranspose(256,
                             3,
                             stride=2,
                             act='relu',
                             padding=1,
                             output_size=conv3.shape,
                             init=init)(conv6)  # 128
    merge7 = Concat()([conv3, tconv7])
    conv7 = Conv2d(256, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(merge7)
    conv7 = BN(act='relu')(conv7) if bn_after_convolutions else conv7
    conv7 = Conv2d(256, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(conv7)
    conv7 = BN(act='relu')(conv7) if bn_after_convolutions else conv7

    tconv8 = Conv2DTranspose(128,
                             stride=2,
                             act='relu',
                             padding=1,
                             output_size=conv2.shape,
                             init=init)(conv7)  # 256
    merge8 = Concat()([conv2, tconv8])
    conv8 = Conv2d(128, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(merge8)
    conv8 = BN(act='relu')(conv8) if bn_after_convolutions else conv8
    conv8 = Conv2d(128, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(conv8)
    conv8 = BN(act='relu')(conv8) if bn_after_convolutions else conv8

    tconv9 = Conv2DTranspose(64,
                             stride=2,
                             act='relu',
                             padding=1,
                             output_size=conv1.shape,
                             init=init)(conv8)  # 512
    merge9 = Concat()([conv1, tconv9])
    conv9 = Conv2d(64, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(merge9)
    conv9 = BN(act='relu')(conv9) if bn_after_convolutions else conv9
    conv9 = Conv2d(64, 3, act=act_conv, init=init,
                   include_bias=bias_conv)(conv9)
    conv9 = BN(act='relu')(conv9) if bn_after_convolutions else conv9

    conv9 = Conv2d(n_classes, 3, act='relu', init=init)(conv9)

    seg1 = Segmentation(name='Segmentation_1')(conv9)
    model = Model(conn, inputs=inp, outputs=seg1, model_table=model_table)
    model.compile()
    return model
Пример #16
0
def MobileNetV2(conn,
                model_table='MobileNetV2',
                n_classes=1000,
                n_channels=3,
                width=224,
                height=224,
                norm_stds=(255 * 0.229, 255 * 0.224, 255 * 0.225),
                offsets=(255 * 0.485, 255 * 0.456, 255 * 0.406),
                random_flip=None,
                random_crop=None,
                random_mutation=None,
                alpha=1):
    '''
    Generates a deep learning model with the MobileNetV2 architecture.
    The implementation is revised based on
    https://github.com/keras-team/keras-applications/blob/master/keras_applications/mobilenet_v2.py

    Parameters
    ----------
    conn : CAS
        Specifies the CAS connection object.
    model_table : string or dict or CAS table, optional
        Specifies the CAS table to store the deep learning model.
    n_classes : int, optional
        Specifies the number of classes. If None is assigned, the model will
        automatically detect the number of classes based on the training set.
        Default: 1000
    n_channels : int, optional
        Specifies the number of the channels (i.e., depth) of the input layer.
        Default: 3
    width : int, optional
        Specifies the width of the input layer.
        Default: 224
    height : int, optional
        Specifies the height of the input layer.
        Default: 224
    norm_stds : double or iter-of-doubles, optional
        Specifies a standard deviation for each channel in the input data.
        The final input data is normalized with specified means and standard deviations.
        Default: (255 * 0.229, 255 * 0.224, 255 * 0.225)
    offsets : double or iter-of-doubles, optional
        Specifies an offset for each channel in the input data. The final input
        data is set after applying scaling and subtracting the specified offsets.
        Default: (255*0.485, 255*0.456, 255*0.406)
    random_flip : string, optional
        Specifies how to flip the data in the input layer when image data is
        used. Approximately half of the input data is subject to flipping.
        Valid Values: 'h', 'hv', 'v', 'none'
    random_crop : string, optional
        Specifies how to crop the data in the input layer when image data is
        used. Images are cropped to the values that are specified in the width
        and height parameters. Only the images with one or both dimensions
        that are larger than those sizes are cropped.
        Valid Values: 'none', 'unique', 'randomresized', 'resizethencrop'
    random_mutation : string, optional
        Specifies how to apply data augmentations/mutations to the data in the input layer.
        Valid Values: 'none', 'random'
    alpha : int, optional
        Specifies the width multiplier in the MobileNet paper
        Default: 1

    alpha : int, optional

    Returns
    -------
    :class:`Model`

    References
    ----------
    https://arxiv.org/abs/1801.04381

    '''
    def _make_divisible(v, divisor, min_value=None):
        # make number of channel divisible
        if min_value is None:
            min_value = divisor
        new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)
        # Make sure that round down does not go down by more than 10%.
        if new_v < 0.9 * v:
            new_v += divisor
        return new_v

    def _inverted_res_block(inputs, in_channels, expansion, stride, alpha,
                            filters, block_id):
        """
        Inverted Residual Block

        Parameters
        ----------
        inputs:
            Input tensor
        in_channels:
            Specifies the number of input tensor's channel
        expansion:
            expansion factor always applied to the input size.
        stride:
            the strides of the convolution
        alpha:
            width multiplier.
        filters:
            the dimensionality of the output space.
        block_id:
            block id used for naming layers

        """
        pointwise_conv_filters = int(filters * alpha)
        pointwise_filters = _make_divisible(pointwise_conv_filters, 8)
        x = inputs
        prefix = 'block_{}_'.format(block_id)
        n_groups = in_channels

        if block_id:
            # Expand
            n_groups = expansion * in_channels
            x = Conv2d(expansion * in_channels,
                       1,
                       include_bias=False,
                       act='identity',
                       name=prefix + 'expand')(x)
            x = BN(name=prefix + 'expand_BN', act='identity')(x)
        else:
            prefix = 'expanded_conv_'

        # Depthwise
        x = GroupConv2d(n_groups,
                        n_groups,
                        3,
                        stride=stride,
                        act='identity',
                        include_bias=False,
                        name=prefix + 'depthwise')(x)
        x = BN(name=prefix + 'depthwise_BN', act='relu')(x)

        # Project
        x = Conv2d(pointwise_filters,
                   1,
                   include_bias=False,
                   act='identity',
                   name=prefix + 'project')(x)
        x = BN(name=prefix + 'project_BN',
               act='identity')(x)  # identity activation on narrow tensor

        if in_channels == pointwise_filters and stride == 1:
            return Res(name=prefix + 'add')([inputs, x]), pointwise_filters
        return x, pointwise_filters

    parameters = locals()
    input_parameters = get_layer_options(input_layer_options, parameters)
    inp = Input(**input_parameters, name='data')
    # compared with mobilenetv1, v2 introduces inverted residual structure.
    # and Non-linearities in narrow layers are removed.
    # inverted residual block does three convolutins: first is 1*1 convolution, second is depthwise convolution,
    # third is 1*1 convolution but without any non-linearity
    first_block_filters = _make_divisible(32 * alpha, 8)
    x = Conv2d(first_block_filters,
               3,
               stride=2,
               include_bias=False,
               name='Conv1',
               act='identity')(inp)
    x = BN(name='bn_Conv1', act='relu')(x)

    x, n_channels = _inverted_res_block(x,
                                        first_block_filters,
                                        filters=16,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=1,
                                        block_id=0)

    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=24,
                                        alpha=alpha,
                                        stride=2,
                                        expansion=6,
                                        block_id=1)
    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=24,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=6,
                                        block_id=2)

    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=32,
                                        alpha=alpha,
                                        stride=2,
                                        expansion=6,
                                        block_id=3)
    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=32,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=6,
                                        block_id=4)
    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=32,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=6,
                                        block_id=5)

    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=64,
                                        alpha=alpha,
                                        stride=2,
                                        expansion=6,
                                        block_id=6)
    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=64,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=6,
                                        block_id=7)
    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=64,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=6,
                                        block_id=8)
    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=64,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=6,
                                        block_id=9)

    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=96,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=6,
                                        block_id=10)
    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=96,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=6,
                                        block_id=11)
    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=96,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=6,
                                        block_id=12)

    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=160,
                                        alpha=alpha,
                                        stride=2,
                                        expansion=6,
                                        block_id=13)
    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=160,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=6,
                                        block_id=14)
    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=160,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=6,
                                        block_id=15)

    x, n_channels = _inverted_res_block(x,
                                        n_channels,
                                        filters=320,
                                        alpha=alpha,
                                        stride=1,
                                        expansion=6,
                                        block_id=16)

    # no alpha applied to last conv as stated in the paper:
    # if the width multiplier is greater than 1 we increase the number of output channels
    if alpha > 1.0:
        last_block_filters = _make_divisible(1280 * alpha, 8)
    else:
        last_block_filters = 1280

    x = Conv2d(last_block_filters,
               1,
               include_bias=False,
               name='Conv_1',
               act='identity')(x)
    x = BN(name='Conv_1_bn', act='relu')(x)

    x = GlobalAveragePooling2D(name="Global_avg_pool")(x)
    x = OutputLayer(n=n_classes)(x)

    model = Model(conn, inp, x, model_table)
    model.compile()

    return model
Пример #17
0
def DenseNet(conn,
             model_table='DenseNet',
             n_classes=None,
             conv_channel=16,
             growth_rate=12,
             n_blocks=4,
             n_cells=4,
             n_channels=3,
             width=32,
             height=32,
             scale=1,
             random_flip=None,
             random_crop=None,
             offsets=(85, 111, 139),
             random_mutation=None):
    '''
    Generates a deep learning model with the DenseNet architecture.

    Parameters
    ----------
    conn : CAS
        Specifies the connection of the CAS connection.
    model_table : string
        Specifies the name of CAS table to store the model.
    n_classes : int, optional
        Specifies the number of classes. If None is assigned, the model will
        automatically detect the number of classes based on the training set.
        Default: None
    conv_channel : int, optional
        Specifies the number of filters of the first convolution layer.
        Default: 16
    growth_rate : int, optional
        Specifies the growth rate of convolution layers.
        Default: 12
    n_blocks : int, optional
        Specifies the number of DenseNet blocks.
        Default: 4
    n_cells : int, optional
        Specifies the number of dense connection for each DenseNet block.
        Default: 4
    n_channels : int, optional
        Specifies the number of the channels (i.e., depth) of the input layer.
        Default: 3
    width : int, optional
        Specifies the width of the input layer.
        Default: 32
    height : int, optional
        Specifies the height of the input layer.
        Default: 32
    scale : double, optional
        Specifies a scaling factor to be applied to each pixel intensity values.
        Default: 1
    random_flip : string, optional
        Specifies how to flip the data in the input layer when image data is
        used. Approximately half of the input data is subject to flipping.
        Valid Values: 'h', 'hv', 'v', 'none'
    random_crop : string, optional
        Specifies how to crop the data in the input layer when image data is
        used. Images are cropped to the values that are specified in the width
        and height parameters. Only the images with one or both dimensions
        that are larger than those sizes are cropped.
        Valid Values: 'none', 'unique', 'randomresized', 'resizethencrop'
    offsets : double or iter-of-doubles, optional
        Specifies an offset for each channel in the input data. The final input
        data is set after applying scaling and subtracting the specified offsets.
        Default: (85, 111, 139)
    random_mutation : string, optional
        Specifies how to apply data augmentations/mutations to the data in the input layer.
        Valid Values: 'none', 'random'

    Returns
    -------
    :class:`Sequential`

    References
    ----------
    https://arxiv.org/pdf/1608.06993.pdf

    '''

    conn.retrieve('loadactionset',
                  _messagelevel='error',
                  actionset='deeplearn')

    # get all the parms passed in
    parameters = locals()

    channel_in = conv_channel  # number of channel of transition conv layer

    model = Sequential(conn=conn, model_table=model_table)

    # get the input parameters
    input_parameters = get_layer_options(input_layer_options, parameters)
    model.add(InputLayer(**input_parameters))

    # Top layers
    model.add(
        Conv2d(conv_channel,
               width=3,
               act='identity',
               include_bias=False,
               stride=1))

    for i in range(n_blocks):
        model.add(
            DenseNetBlock(n_cells=n_cells,
                          kernel_size=3,
                          n_filter=growth_rate,
                          stride=1))
        # transition block
        channel_in += (growth_rate * n_cells)
        model.add(BN(act='relu'))
        if i != (n_blocks - 1):
            model.add(
                Conv2d(channel_in,
                       width=3,
                       act='identity',
                       include_bias=False,
                       stride=1))
            model.add(Pooling(width=2, height=2, pool='mean'))

    model.add(GlobalAveragePooling2D())

    model.add(OutputLayer(act='softmax', n=n_classes))

    return model
Пример #18
0
def DenseNet121(conn,
                model_table='DENSENET121',
                n_classes=1000,
                conv_channel=64,
                growth_rate=32,
                n_cells=[6, 12, 24, 16],
                n_channels=3,
                reduction=0.5,
                width=224,
                height=224,
                scale=1,
                random_flip=None,
                random_crop=None,
                offsets=(103.939, 116.779, 123.68),
                random_mutation=None):
    '''
    Generates a deep learning model with the DenseNet121 architecture.

    Parameters
    ----------
    conn : CAS
        Specifies the connection of the CAS connection.
    model_table : string
        Specifies the name of CAS table to store the model.
    n_classes : int, optional
        Specifies the number of classes. If None is assigned, the model will
        automatically detect the number of classes based on the training set.
        Default: 1000
    conv_channel : int, optional
        Specifies the number of filters of the first convolution layer.
        Default: 64
    growth_rate : int, optional
        Specifies the growth rate of convolution layers.
        Default: 32
    n_cells : int array length=4, optional
        Specifies the number of dense connection for each DenseNet block.
        Default: [6, 12, 24, 16]
    reduction : double, optional
        Specifies the factor of transition blocks.
        Default: 0.5
    n_channels : int, optional
        Specifies the number of the channels (i.e., depth) of the input layer.
        Default: 3.
    width : int, optional
        Specifies the width of the input layer.
        Default: 224.
    height : int, optional
        Specifies the height of the input layer.
        Default: 224.
    scale : double, optional
        Specifies a scaling factor to be applied to each pixel intensity values.
        Default: 1.
    random_flip : string, optional
        Specifies how to flip the data in the input layer when image data is
        used. Approximately half of the input data is subject to flipping.
        Valid Values: 'h', 'hv', 'v', 'none'
    random_crop : string, optional
        Specifies how to crop the data in the input layer when image data is
        used. Images are cropped to the values that are specified in the width
        and height parameters. Only the images with one or both dimensions
        that are larger than those sizes are cropped.
        Valid Values: 'none', 'unique', 'randomresized', 'resizethencrop'
    offsets : double or iter-of-doubles, optional
        Specifies an offset for each channel in the input data. The final input
        data is set after applying scaling and subtracting the specified offsets.
        Default: (103.939, 116.779, 123.68)
    random_mutation : string, optional
        Specifies how to apply data augmentations/mutations to the data in the input layer.
        Valid Values: 'none', 'random'

    Returns
    -------
    :class:`Sequential`

    References
    ----------
    https://arxiv.org/pdf/1608.06993.pdf

    '''

    conn.retrieve('loadactionset',
                  _messagelevel='error',
                  actionset='deeplearn')

    # get all the parms passed in
    parameters = locals()

    n_blocks = len(n_cells)

    model = Sequential(conn=conn, model_table=model_table)

    # get the input parameters
    input_parameters = get_layer_options(input_layer_options, parameters)
    model.add(InputLayer(**input_parameters))

    # Top layers
    model.add(
        Conv2d(conv_channel,
               width=7,
               act='identity',
               include_bias=False,
               stride=2))
    model.add(BN(act='relu'))
    src_layer = Pooling(width=3, height=3, stride=2, padding=1, pool='max')
    model.add(src_layer)

    for i in range(n_blocks):
        for _ in range(n_cells[i]):

            model.add(BN(act='relu'))
            model.add(
                Conv2d(n_filters=growth_rate * 4,
                       width=1,
                       act='identity',
                       stride=1,
                       include_bias=False))

            model.add(BN(act='relu'))
            src_layer2 = Conv2d(n_filters=growth_rate,
                                width=3,
                                act='identity',
                                stride=1,
                                include_bias=False)

            model.add(src_layer2)
            src_layer = Concat(act='identity',
                               src_layers=[src_layer, src_layer2])
            model.add(src_layer)

            conv_channel += growth_rate

        if i != (n_blocks - 1):
            # transition block
            conv_channel = int(conv_channel * reduction)

            model.add(BN(act='relu'))
            model.add(
                Conv2d(n_filters=conv_channel,
                       width=1,
                       act='identity',
                       stride=1,
                       include_bias=False))
            src_layer = Pooling(width=2, height=2, stride=2, pool='mean')

            model.add(src_layer)

    model.add(BN(act='identity'))
    # Bottom Layers
    model.add(GlobalAveragePooling2D())

    model.add(OutputLayer(act='softmax', n=n_classes))

    return model
Пример #19
0
def ShuffleNetV1(conn,
                 model_table='ShuffleNetV1',
                 n_classes=1000,
                 n_channels=3,
                 width=224,
                 height=224,
                 norm_stds=(255 * 0.229, 255 * 0.224, 255 * 0.225),
                 offsets=(255 * 0.485, 255 * 0.456, 255 * 0.406),
                 random_flip=None,
                 random_crop=None,
                 random_mutation=None,
                 scale_factor=1.0,
                 num_shuffle_units=[3, 7, 3],
                 bottleneck_ratio=0.25,
                 groups=3,
                 block_act='identity'):
    '''
    Generates a deep learning model with the ShuffleNetV1 architecture.
    The implementation is revised based on https://github.com/scheckmedia/keras-shufflenet/blob/master/shufflenet.py

    Parameters
    ----------
    conn : CAS
        Specifies the CAS connection object.
    model_table : string or dict or CAS table, optional
        Specifies the CAS table to store the deep learning model.
    n_classes : int, optional
        Specifies the number of classes. If None is assigned, the model will
        automatically detect the number of classes based on the training set.
        Default: 1000
    n_channels : int, optional
        Specifies the number of the channels (i.e., depth) of the input layer.
        Default: 3
    width : int, optional
        Specifies the width of the input layer.
        Default: 32
    height : int, optional
        Specifies the height of the input layer.
        Default: 32
    norm_stds : double or iter-of-doubles, optional
        Specifies a standard deviation for each channel in the input data.
        The final input data is normalized with specified means and standard deviations.
        Default: (255 * 0.229, 255 * 0.224, 255 * 0.225)
    offsets : double or iter-of-doubles, optional
        Specifies an offset for each channel in the input data. The final input
        data is set after applying scaling and subtracting the specified offsets.
        Default: (255*0.485, 255*0.456, 255*0.406)
    random_flip : string, optional
        Specifies how to flip the data in the input layer when image data is
        used. Approximately half of the input data is subject to flipping.
        Valid Values: 'h', 'hv', 'v', 'none'
    random_crop : string, optional
        Specifies how to crop the data in the input layer when image data is
        used. Images are cropped to the values that are specified in the width
        and height parameters. Only the images with one or both dimensions
        that are larger than those sizes are cropped.
        Valid Values: 'none', 'unique', 'randomresized', 'resizethencrop'
    random_mutation : string, optional
        Specifies how to apply data augmentations/mutations to the data in the input layer.
        Valid Values: 'none', 'random'
    scale_factor : double

    num_shuffle_units: iter-of-int, optional
        number of stages (list length) and the number of shufflenet units in a
        stage beginning with stage 2 because stage 1 is fixed
        e.g. idx 0 contains 3 + 1 (first shuffle unit in each stage differs) shufflenet units for stage 2
        idx 1 contains 7 + 1 Shufflenet Units for stage 3 and
        idx 2 contains 3 + 1 Shufflenet Units
        Default: [3, 7, 3]
    bottleneck_ratio : double
        bottleneck ratio implies the ratio of bottleneck channels to output channels.
        For example, bottleneck ratio = 1 : 4 means the output feature map is 4 times
        the width of the bottleneck feature map.
    groups: int
        Specifies the number of groups per channel
        Default : 3
    block_act : str
        Specifies the activation function after depth-wise convolution and batch normalization layer
        Default : 'identity'

    Returns
    -------
    :class:`Model`

    References
    ----------
    https://arxiv.org/pdf/1707.01083

    '''
    def _block(x, channel_map, bottleneck_ratio, repeat=1, groups=1, stage=1):
        """
        creates a bottleneck block

        Parameters
        ----------
        x:
            Input tensor
        channel_map:
            list containing the number of output channels for a stage
        repeat:
            number of repetitions for a shuffle unit with stride 1
        groups:
            number of groups per channel
        bottleneck_ratio:
            bottleneck ratio implies the ratio of bottleneck channels to output channels.
        stage:
            stage number

        Returns
        -------
        """
        x = _shuffle_unit(x,
                          in_channels=channel_map[stage - 2],
                          out_channels=channel_map[stage - 1],
                          strides=2,
                          groups=groups,
                          bottleneck_ratio=bottleneck_ratio,
                          stage=stage,
                          block=1)

        for i in range(1, repeat + 1):
            x = _shuffle_unit(x,
                              in_channels=channel_map[stage - 1],
                              out_channels=channel_map[stage - 1],
                              strides=1,
                              groups=groups,
                              bottleneck_ratio=bottleneck_ratio,
                              stage=stage,
                              block=(i + 1))

        return x

    def _shuffle_unit(inputs,
                      in_channels,
                      out_channels,
                      groups,
                      bottleneck_ratio,
                      strides=2,
                      stage=1,
                      block=1):
        """
        create a shuffle unit

        Parameters
        ----------
        inputs:
            Input tensor of with `channels_last` data format
        in_channels:
            number of input channels
        out_channels:
            number of output channels
        strides:
            An integer or tuple/list of 2 integers,
        groups:
            number of groups per channel
        bottleneck_ratio: float
            bottleneck ratio implies the ratio of bottleneck channels to output channels.
        stage:
            stage number
        block:
            block number

        """
        prefix = 'stage%d/block%d' % (stage, block)

        # if strides >= 2:
        # out_channels -= in_channels

        # default: 1/4 of the output channel of a ShuffleNet Unit
        bottleneck_channels = int(out_channels * bottleneck_ratio)
        groups = (1 if stage == 2 and block == 1 else groups)

        # x = _group_conv(inputs, in_channels, out_channels = bottleneck_channels,
        #                 groups = (1 if stage == 2 and block == 1 else groups),
        #                 name = '%s/1x1_gconv_1' % prefix)

        x = GroupConv2d(bottleneck_channels,
                        n_groups=(1 if stage == 2 and block == 1 else groups),
                        act='identity',
                        width=1,
                        height=1,
                        stride=1,
                        include_bias=False,
                        name='%s/1x1_gconv_1' % prefix)(inputs)

        x = BN(act='relu', name='%s/bn_gconv_1' % prefix)(x)

        x = ChannelShuffle(n_groups=groups,
                           name='%s/channel_shuffle' % prefix)(x)
        # depthwise convolutioin
        x = GroupConv2d(x.shape[-1],
                        n_groups=x.shape[-1],
                        width=3,
                        height=3,
                        include_bias=False,
                        stride=strides,
                        act='identity',
                        name='%s/1x1_dwconv_1' % prefix)(x)
        x = BN(act=block_act, name='%s/bn_dwconv_1' % prefix)(x)

        out_channels = out_channels if strides == 1 else out_channels - in_channels
        x = GroupConv2d(out_channels,
                        n_groups=groups,
                        width=1,
                        height=1,
                        stride=1,
                        act='identity',
                        include_bias=False,
                        name='%s/1x1_gconv_2' % prefix)(x)

        x = BN(act=block_act, name='%s/bn_gconv_2' % prefix)(x)

        if strides < 2:
            ret = Res(act='relu', name='%s/add' % prefix)([x, inputs])
        else:
            avg = Pooling(width=3,
                          height=3,
                          stride=2,
                          pool='mean',
                          name='%s/avg_pool' % prefix)(inputs)
            ret = Concat(act='relu', name='%s/concat' % prefix)([x, avg])

        return ret

    out_dim_stage_two = {1: 144, 2: 200, 3: 240, 4: 272, 8: 384}
    try:
        import numpy as np
    except:
        raise DLPyError('Please install numpy to use this architecture.')

    exp = np.insert(np.arange(0, len(num_shuffle_units), dtype=np.float32), 0,
                    0)
    out_channels_in_stage = 2**exp
    out_channels_in_stage *= out_dim_stage_two[
        groups]  # calculate output channels for each stage
    out_channels_in_stage[0] = 24  # first stage has always 24 output channels
    out_channels_in_stage *= scale_factor
    out_channels_in_stage = out_channels_in_stage.astype(int)

    parameters = locals()
    input_parameters = get_layer_options(input_layer_options, parameters)
    inp = Input(**input_parameters, name='data')

    # create shufflenet architecture
    x = Conv2d(out_channels_in_stage[0],
               3,
               include_bias=False,
               stride=2,
               act="identity",
               name="conv1")(inp)
    x = BN(act='relu', name='bn1')(x)
    x = Pooling(width=3, height=3, stride=2, name="maxpool1")(x)

    # create stages containing shufflenet units beginning at stage 2
    for stage in range(0, len(num_shuffle_units)):
        repeat = num_shuffle_units[stage]
        x = _block(x,
                   out_channels_in_stage,
                   repeat=repeat,
                   bottleneck_ratio=bottleneck_ratio,
                   groups=groups,
                   stage=stage + 2)

    x = GlobalAveragePooling2D(name="Global_avg_pool")(x)
    x = OutputLayer(n=n_classes)(x)

    model = Model(conn, inputs=inp, outputs=x, model_table=model_table)
    model.compile()

    return model
Пример #20
0
    def _shuffle_unit(inputs,
                      in_channels,
                      out_channels,
                      groups,
                      bottleneck_ratio,
                      strides=2,
                      stage=1,
                      block=1):
        """
        create a shuffle unit

        Parameters
        ----------
        inputs:
            Input tensor of with `channels_last` data format
        in_channels:
            number of input channels
        out_channels:
            number of output channels
        strides:
            An integer or tuple/list of 2 integers,
        groups:
            number of groups per channel
        bottleneck_ratio: float
            bottleneck ratio implies the ratio of bottleneck channels to output channels.
        stage:
            stage number
        block:
            block number

        """
        prefix = 'stage%d/block%d' % (stage, block)

        # if strides >= 2:
        # out_channels -= in_channels

        # default: 1/4 of the output channel of a ShuffleNet Unit
        bottleneck_channels = int(out_channels * bottleneck_ratio)
        groups = (1 if stage == 2 and block == 1 else groups)

        # x = _group_conv(inputs, in_channels, out_channels = bottleneck_channels,
        #                 groups = (1 if stage == 2 and block == 1 else groups),
        #                 name = '%s/1x1_gconv_1' % prefix)

        x = GroupConv2d(bottleneck_channels,
                        n_groups=(1 if stage == 2 and block == 1 else groups),
                        act='identity',
                        width=1,
                        height=1,
                        stride=1,
                        include_bias=False,
                        name='%s/1x1_gconv_1' % prefix)(inputs)

        x = BN(act='relu', name='%s/bn_gconv_1' % prefix)(x)

        x = ChannelShuffle(n_groups=groups,
                           name='%s/channel_shuffle' % prefix)(x)
        # depthwise convolutioin
        x = GroupConv2d(x.shape[-1],
                        n_groups=x.shape[-1],
                        width=3,
                        height=3,
                        include_bias=False,
                        stride=strides,
                        act='identity',
                        name='%s/1x1_dwconv_1' % prefix)(x)
        x = BN(act=block_act, name='%s/bn_dwconv_1' % prefix)(x)

        out_channels = out_channels if strides == 1 else out_channels - in_channels
        x = GroupConv2d(out_channels,
                        n_groups=groups,
                        width=1,
                        height=1,
                        stride=1,
                        act='identity',
                        include_bias=False,
                        name='%s/1x1_gconv_2' % prefix)(x)

        x = BN(act=block_act, name='%s/bn_gconv_2' % prefix)(x)

        if strides < 2:
            ret = Res(act='relu', name='%s/add' % prefix)([x, inputs])
        else:
            avg = Pooling(width=3,
                          height=3,
                          stride=2,
                          pool='mean',
                          name='%s/avg_pool' % prefix)(inputs)
            ret = Concat(act='relu', name='%s/concat' % prefix)([x, avg])

        return ret
Пример #21
0
def Darknet_Reference(conn,
                      model_table='Darknet_Reference',
                      n_classes=1000,
                      act='leaky',
                      n_channels=3,
                      width=224,
                      height=224,
                      scale=1.0 / 255,
                      random_flip='H',
                      random_crop='UNIQUE',
                      random_mutation=None):
    '''
    Generates a deep learning model with the Darknet_Reference architecture.

    The head of the model except the last convolutional layer is same as
    the head of Tiny Yolov2. Darknet Reference is pre-trained model for
    ImageNet classification.

    Parameters
    ----------
    conn : CAS
        Specifies the connection of the CAS connection.
    model_table : string
        Specifies the name of CAS table to store the model.
    n_classes : int, optional
        Specifies the number of classes. If None is assigned, the model will
        automatically detect the number of classes based on the training set.
        Default: 1000
    act : string
        Specifies the type of the activation function for the batch
        normalization layers and the final convolution layer.
        Default: 'leaky'
    n_channels : int, optional
        Specifies the number of the channels (i.e., depth) of the input layer.
        Default: 3.
    width : int, optional
        Specifies the width of the input layer.
        Default: 224.
    height : int, optional
        Specifies the height of the input layer.
        Default: 224.
    scale : double, optional
        Specifies a scaling factor to be applied to each pixel intensity values.
        Default: 1.0 / 255
    random_flip : string, optional
        Specifies how to flip the data in the input layer when image data is
        used. Approximately half of the input data is subject to flipping.
        Valid Values: 'h', 'hv', 'v', 'none'
        Default: 'h'
    random_crop : string, optional
        Specifies how to crop the data in the input layer when image data is
        used. Images are cropped to the values that are specified in the width
        and height parameters. Only the images with one or both dimensions
        that are larger than those sizes are cropped.
        Valid Values: 'none', 'unique', 'randomresized', 'resizethencrop'
        Default: 'unique'
    random_mutation : string, optional
        Specifies how to apply data augmentations/mutations to the data in the input layer.
        Valid Values: 'none', 'random'

    Returns
    -------
    :class:`Sequential`

    '''

    conn.retrieve('loadactionset',
                  _messagelevel='error',
                  actionset='deeplearn')

    # get all the parms passed in
    parameters = locals()

    model = Sequential(conn=conn, model_table=model_table)

    # get the input parameters
    input_parameters = get_layer_options(input_layer_options, parameters)
    model.add(InputLayer(**input_parameters))

    # conv1 224
    model.add(Conv2d(16, width=3, act='identity', include_bias=False,
                     stride=1))
    model.add(BN(act=act))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))
    # conv2 112
    model.add(Conv2d(32, width=3, act='identity', include_bias=False,
                     stride=1))
    model.add(BN(act=act))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))
    # conv3 56
    model.add(Conv2d(64, width=3, act='identity', include_bias=False,
                     stride=1))
    model.add(BN(act=act))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))
    # conv4 28
    model.add(
        Conv2d(128, width=3, act='identity', include_bias=False, stride=1))
    model.add(BN(act=act))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))
    # conv5 14
    model.add(
        Conv2d(256, width=3, act='identity', include_bias=False, stride=1))
    model.add(BN(act=act))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))
    # conv6 7
    model.add(
        Conv2d(512, width=3, act='identity', include_bias=False, stride=1))
    model.add(BN(act=act))
    model.add(Pooling(width=2, height=2, stride=1, pool='max'))
    # conv7 7
    model.add(
        Conv2d(1024, width=3, act='identity', include_bias=False, stride=1))
    model.add(BN(act=act))
    # conv8 7
    model.add(Conv2d(1000, width=1, act=act, include_bias=True, stride=1))

    model.add(GlobalAveragePooling2D())
    model.add(OutputLayer(act='softmax', n=n_classes))

    return model
Пример #22
0
    def test_model4(self):
        try:
            import onnx
            from onnx import numpy_helper
        except:
            unittest.TestCase.skipTest(self, "onnx not found in the libraries")

        import numpy as np

        model1 = Sequential(self.s, model_table='Simple_CNN1')
        model1.add(InputLayer(3, 224, 224))
        model1.add(Conv2d(8, 7, act='identity', include_bias=False))
        model1.add(Reshape(height=448, width=448, depth=2, act='IDENTITY'))
        model1.add(Reshape(height=448, width=448, depth=2, act='RECTIFIER'))
        model1.add(Conv2d(8, 7, act='identity', include_bias=False))
        model1.add(BN(act='relu'))
        model1.add(Dense(2))
        model1.add(OutputLayer(act='softmax', n=2))

        if self.data_dir is None:
            unittest.TestCase.skipTest(
                self, "DLPY_DATA_DIR is not set in the environment variables")

        caslib, path, tmp_caslib = caslibify(self.s,
                                             path=self.data_dir +
                                             'images.sashdat',
                                             task='load')

        self.s.table.loadtable(caslib=caslib,
                               casout={
                                   'name': 'eee',
                                   'replace': True
                               },
                               path=path)

        r = model1.fit(data='eee',
                       inputs='_image_',
                       target='_label_',
                       max_epochs=1)
        self.assertTrue(r.severity == 0)

        if self.data_dir_local is None:
            unittest.TestCase.skipTest(
                self,
                "DLPY_DATA_DIR_LOCAL is not set in the environment variables")

        #model1.deploy(self.data_dir_local, output_format='onnx')

        import tempfile
        tmp_dir_to_dump = tempfile.gettempdir()

        model1.deploy(tmp_dir_to_dump, output_format='onnx')
        import os
        model_path = os.path.join(tmp_dir_to_dump, 'Simple_CNN1.onnx')

        m = onnx.load(model_path)
        self.assertEqual(m.graph.node[1].op_type, 'Reshape')
        init = numpy_helper.to_array(m.graph.initializer[1])
        self.assertTrue(np.array_equal(init, [-1, 2, 448, 448]))

        import os
        os.remove(os.path.join(tmp_dir_to_dump, "Simple_CNN1.onnx"))

        if (caslib is not None) and tmp_caslib:
            self.s.retrieve('table.dropcaslib',
                            message_level='error',
                            caslib=caslib)
Пример #23
0
    def test_stride(self):
        model = Sequential(self.s, model_table = 'Simple_CNN_3classes_cropped')
        model.add(InputLayer(1, width = 36, height = 144, #offsets = myimage.channel_means,
                             name = 'input1',
                             random_mutation = 'random',
                             random_flip = 'HV'))

        model.add(Conv2d(64, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Conv2d(64, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Conv2d(64, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Pooling(height = 2, width = 2, stride_vertical = 2, stride_horizontal = 1, pool = 'max'))  # 72, 36

        model.add(Conv2d(128, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Conv2d(128, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Conv2d(128, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Pooling(height = 2, width = 2, stride_vertical = 2, stride_horizontal = 1, pool = 'max'))  # 36*36

        model.add(Conv2d(256, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Conv2d(256, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Conv2d(256, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Pooling(2, pool = 'max'))  # 18 * 18

        model.add(Conv2d(512, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Conv2d(512, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Conv2d(512, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Pooling(2, pool = 'max'))  # 9 * 9

        model.add(Conv2d(1024, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Conv2d(1024, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Conv2d(1024, 3, 3, include_bias = False, act = 'identity'))
        model.add(BN(act = 'relu'))
        model.add(Pooling(9))

        model.add(Dense(256, dropout = 0.5))
        model.add(OutputLayer(act = 'softmax', n = 3, name = 'output1'))
        self.assertEqual(model.summary['Output Size'].values[-3], (1, 1, 1024))
        model.print_summary()
        # 2d print summary numerical check
        self.assertEqual(model.summary.iloc[1, -1], 2985984)
Пример #24
0
def Tiny_YoloV2(conn,
                anchors,
                model_table='Tiny-Yolov2',
                n_channels=3,
                width=416,
                height=416,
                scale=1.0 / 255,
                random_mutation=None,
                act='leaky',
                act_detection='AUTO',
                softmax_for_class_prob=True,
                coord_type='YOLO',
                max_label_per_image=30,
                max_boxes=30,
                n_classes=20,
                predictions_per_grid=5,
                do_sqrt=True,
                grid_number=13,
                coord_scale=None,
                object_scale=None,
                prediction_not_a_object_scale=None,
                class_scale=None,
                detection_threshold=None,
                iou_threshold=None,
                random_boxes=False,
                match_anchor_size=None,
                num_to_force_coord=None,
                random_flip=None,
                random_crop=None):
    '''
    Generate a deep learning model with the Tiny Yolov2 architecture.

    Tiny Yolov2 is a very small model of Yolov2, so that it includes fewer
    numbers of convolutional layer and batch normalization layer.

    Parameters
    ----------
    conn : CAS
        Specifies the connection of the CAS connection.
    anchors : list
        Specifies the anchor box values.
    model_table : string, optional
        Specifies the name of CAS table to store the model.
    n_channels : int, optional
        Specifies the number of the channels (i.e., depth) of the input layer.
        Default: 3
    width : int, optional
        Specifies the width of the input layer.
        Default: 416
    height : int, optional
        Specifies the height of the input layer.
        Default: 416
    scale : double, optional
        Specifies a scaling factor to be applied to each pixel intensity values.
        Default: 1.0 / 255
    random_mutation : string, optional
        Specifies how to apply data augmentations/mutations to the data in the
        input layer.
        Valid Values: 'none', 'random'
    act : string, optional
        Specifies the activation function for the batch normalization layers.
        Default: 'leaky'
    act_detection : string, optional
        Specifies the activation function for the detection layer.
        Valid Values: AUTO, IDENTITY, LOGISTIC, SIGMOID, TANH, RECTIFIER, RELU, SOFPLUS, ELU, LEAKY, FCMP
        Default: AUTO
    softmax_for_class_prob : bool, optional
        Specifies whether to perform Softmax on class probability per
        predicted object.
        Default: True
    coord_type : string, optional
        Specifies the format of how to represent bounding boxes. For example,
        a bounding box can be represented with the x and y locations of the
        top-left point as well as width and height of the rectangle.
        This format is the 'rect' format. We also support coco and yolo formats.
        Valid Values: 'rect', 'yolo', 'coco'
        Default: 'yolo'
    max_label_per_image : int, optional
        Specifies the maximum number of labels per image in the training.
        Default: 30
    max_boxes : int, optional
        Specifies the maximum number of overall predictions allowed in the
        detection layer.
        Default: 30
    n_classes : int, optional
        Specifies the number of classes. If None is assigned, the model will
        automatically detect the number of classes based on the training set.
        Default: 20
    predictions_per_grid : int, optional
        Specifies the amount of predictions will be done per grid.
        Default: 5
    do_sqrt : bool, optional
        Specifies whether to apply the SQRT function to width and height of
        the object for the cost function.
        Default: True
    grid_number : int, optional
        Specifies the amount of cells to be analyzed for an image. For example,
        if the value is 5, then the image will be divided into a 5 x 5 grid.
        Default: 13
    coord_scale : float, optional
        Specifies the weight for the cost function in the detection layer,
        when objects exist in the grid.
    object_scale : float, optional
        Specifies the weight for object detected for the cost function in
        the detection layer.
    prediction_not_a_object_scale : float, optional
        Specifies the weight for the cost function in the detection layer,
        when objects do not exist in the grid.
    class_scale : float, optional
        Specifies the weight for the class of object detected for the cost
        function in the detection layer.
    detection_threshold : float, optional
        Specifies the threshold for object detection.
    iou_threshold : float, optional
        Specifies the IOU Threshold of maximum suppression in object detection.
    random_boxes : bool, optional
        Randomizing boxes when loading the bounding box information.
        Default: False
    match_anchor_size : bool, optional
        Whether to force the predicted box match the anchor boxes in sizes for all predictions
    num_to_force_coord : int, optional
        The number of leading chunk of images in training when the algorithm forces predicted objects
        in each grid to be equal to the anchor box sizes, and located at the grid center
    random_flip : string, optional
        Specifies how to flip the data in the input layer when image data is
        used. Approximately half of the input data is subject to flipping.
        Valid Values: 'h', 'hv', 'v', 'none'
    random_crop : string, optional
        Specifies how to crop the data in the input layer when image data is
        used. Images are cropped to the values that are specified in the width
        and height parameters. Only the images with one or both dimensions
        that are larger than those sizes are cropped.
        Valid Values: 'none', 'unique', 'randomresized', 'resizethencrop'

    Returns
    -------
    :class:`Sequential`

    References
    ----------
    https://arxiv.org/pdf/1612.08242.pdf

    '''

    model = Sequential(conn=conn, model_table=model_table)

    parameters = locals()
    input_parameters = get_layer_options(input_layer_options, parameters)
    model.add(InputLayer(**input_parameters))

    # conv1 416 448
    model.add(
        Conv2d(n_filters=16,
               width=3,
               act='identity',
               include_bias=False,
               stride=1))
    model.add(BN(act=act))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))
    # conv2 208 224
    model.add(
        Conv2d(n_filters=32,
               width=3,
               act='identity',
               include_bias=False,
               stride=1))
    model.add(BN(act=act))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))
    # conv3 104 112
    model.add(
        Conv2d(n_filters=64,
               width=3,
               act='identity',
               include_bias=False,
               stride=1))
    model.add(BN(act=act))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))
    # conv4 52 56
    model.add(
        Conv2d(n_filters=128,
               width=3,
               act='identity',
               include_bias=False,
               stride=1))
    model.add(BN(act=act))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))
    # conv5 26 28
    model.add(
        Conv2d(n_filters=256,
               width=3,
               act='identity',
               include_bias=False,
               stride=1))
    model.add(BN(act=act))
    model.add(Pooling(width=2, height=2, stride=2, pool='max'))
    # conv6 13 14
    model.add(
        Conv2d(n_filters=512,
               width=3,
               act='identity',
               include_bias=False,
               stride=1))
    model.add(BN(act=act))
    model.add(Pooling(width=2, height=2, stride=1, pool='max'))
    # conv7 13
    model.add(
        Conv2d(n_filters=1024,
               width=3,
               act='identity',
               include_bias=False,
               stride=1))
    model.add(BN(act=act))
    # conv8 13
    model.add(
        Conv2d(n_filters=512,
               width=3,
               act='identity',
               include_bias=False,
               stride=1))
    model.add(BN(act=act))

    model.add(
        Conv2d((n_classes + 5) * predictions_per_grid,
               width=1,
               act='identity',
               include_bias=False,
               stride=1))

    model.add(
        Detection(act=act_detection,
                  detection_model_type='yolov2',
                  anchors=anchors,
                  softmax_for_class_prob=softmax_for_class_prob,
                  coord_type=coord_type,
                  class_number=n_classes,
                  grid_number=grid_number,
                  predictions_per_grid=predictions_per_grid,
                  do_sqrt=do_sqrt,
                  coord_scale=coord_scale,
                  object_scale=object_scale,
                  prediction_not_a_object_scale=prediction_not_a_object_scale,
                  class_scale=class_scale,
                  detection_threshold=detection_threshold,
                  iou_threshold=iou_threshold,
                  random_boxes=random_boxes,
                  max_label_per_image=max_label_per_image,
                  max_boxes=max_boxes,
                  match_anchor_size=match_anchor_size,
                  num_to_force_coord=num_to_force_coord))
    return model
Пример #25
0
    def _inverted_res_block(inputs, in_channels, expansion, stride, alpha,
                            filters, block_id):
        """
        Inverted Residual Block

        Parameters
        ----------
        inputs:
            Input tensor
        in_channels:
            Specifies the number of input tensor's channel
        expansion:
            expansion factor always applied to the input size.
        stride:
            the strides of the convolution
        alpha:
            width multiplier.
        filters:
            the dimensionality of the output space.
        block_id:
            block id used for naming layers

        """
        pointwise_conv_filters = int(filters * alpha)
        pointwise_filters = _make_divisible(pointwise_conv_filters, 8)
        x = inputs
        prefix = 'block_{}_'.format(block_id)
        n_groups = in_channels

        if block_id:
            # Expand
            n_groups = expansion * in_channels
            x = Conv2d(expansion * in_channels,
                       1,
                       include_bias=False,
                       act='identity',
                       name=prefix + 'expand')(x)
            x = BN(name=prefix + 'expand_BN', act='identity')(x)
        else:
            prefix = 'expanded_conv_'

        # Depthwise
        x = GroupConv2d(n_groups,
                        n_groups,
                        3,
                        stride=stride,
                        act='identity',
                        include_bias=False,
                        name=prefix + 'depthwise')(x)
        x = BN(name=prefix + 'depthwise_BN', act='relu')(x)

        # Project
        x = Conv2d(pointwise_filters,
                   1,
                   include_bias=False,
                   act='identity',
                   name=prefix + 'project')(x)
        x = BN(name=prefix + 'project_BN',
               act='identity')(x)  # identity activation on narrow tensor

        if in_channels == pointwise_filters and stride == 1:
            return Res(name=prefix + 'add')([inputs, x]), pointwise_filters
        return x, pointwise_filters
Пример #26
0
def InceptionV3(conn,
                model_table='InceptionV3',
                n_classes=1000,
                n_channels=3,
                width=299,
                height=299,
                scale=1,
                random_flip=None,
                random_crop=None,
                offsets=(103.939, 116.779, 123.68),
                pre_trained_weights=False,
                pre_trained_weights_file=None,
                include_top=False,
                random_mutation=None):
    '''
    Generates a deep learning model with the Inceptionv3 architecture with batch normalization layers.

    Parameters
    ----------
    conn : CAS
        Specifies the CAS connection object.
    model_table : string, optional
        Specifies the name of CAS table to store the model in.
    n_classes : int, optional
        Specifies the number of classes. If None is assigned, the model will
        automatically detect the number of classes based on the training set.
        Default: 1000
    n_channels : int, optional
        Specifies the number of the channels (i.e., depth) of the input layer.
        Default: 3
    width : int, optional
        Specifies the width of the input layer.
        Default: 299
    height : int, optional
        Specifies the height of the input layer.
        Default: 299
    scale : double, optional
        Specifies a scaling factor to be applied to each pixel intensity values.
        Default: 1.0
    random_flip : string, optional
        Specifies how to flip the data in the input layer when image data is
        used. Approximately half of the input data is subject to flipping.
        Valid Values: 'h', 'hv', 'v', 'none'
    random_crop : string, optional
        Specifies how to crop the data in the input layer when image data is
        used. Images are cropped to the values that are specified in the width
        and height parameters. Only the images with one or both dimensions
        that are larger than those sizes are cropped.
        Valid Values: 'none', 'unique', 'randomresized', 'resizethencrop'
    offsets : double or iter-of-doubles, optional
        Specifies an offset for each channel in the input data. The final input
        data is set after applying scaling and subtracting the specified offsets.
        Default: (103.939, 116.779, 123.68)
    pre_trained_weights : bool, optional
        Specifies whether to use the pre-trained weights from ImageNet data set
        Default: False
    pre_trained_weights_file : string, optional
        Specifies the file name for the pretained weights.
        Must be a fully qualified file name of SAS-compatible file (*.caffemodel.h5)
        Note: Required when pre_train_weight=True.
    include_top : bool, optional
        Specifies whether to include pre-trained weights of the top layers,
        i.e. the FC layers
        Default: False
    random_mutation : string, optional
        Specifies how to apply data augmentations/mutations to the data in the input layer.
        Valid Values: 'none', 'random'

    Returns
    -------
    :class:`Sequential`
        If `pre_train_weight` is `False`
    :class:`Model`
        If `pre_train_weight` is `True`

    References
    ----------
    https://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Szegedy_Rethinking_the_Inception_CVPR_2016_paper.pdf

    '''

    conn.retrieve('loadactionset',
                  _messagelevel='error',
                  actionset='deeplearn')

    # get all the parms passed in
    parameters = locals()

    if not pre_trained_weights:
        model = Sequential(conn=conn, model_table=model_table)

        # get the input parameters
        input_parameters = get_layer_options(input_layer_options, parameters)
        model.add(InputLayer(**input_parameters))

        # 299 x 299 x 3
        model.add(
            Conv2d(n_filters=32,
                   width=3,
                   height=3,
                   stride=2,
                   act='identity',
                   include_bias=False,
                   padding=0))
        model.add(BN(act='relu'))
        # 149 x 149 x 32
        model.add(
            Conv2d(n_filters=32,
                   width=3,
                   height=3,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   padding=0))
        model.add(BN(act='relu'))
        # 147 x 147 x 32
        model.add(
            Conv2d(n_filters=64,
                   width=3,
                   height=3,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        # 147 x 147 x 64
        model.add(Pooling(width=3, height=3, stride=2, pool='max', padding=0))

        # 73 x 73 x 64
        model.add(
            Conv2d(n_filters=80,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   padding=0))
        model.add(BN(act='relu'))
        # 73 x 73 x 80
        model.add(
            Conv2d(n_filters=192,
                   width=3,
                   height=3,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   padding=0))
        model.add(BN(act='relu'))
        # 71 x 71 x 192
        pool2 = Pooling(width=3, height=3, stride=2, pool='max', padding=0)
        model.add(pool2)

        # mixed 0: output 35 x 35 x 256

        # branch1x1
        model.add(
            Conv2d(n_filters=64,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[pool2]))
        branch1x1 = BN(act='relu')
        model.add(branch1x1)

        # branch5x5
        model.add(
            Conv2d(n_filters=48,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[pool2]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=64,
                   width=5,
                   height=5,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch5x5 = BN(act='relu')
        model.add(branch5x5)

        # branch3x3dbl
        model.add(
            Conv2d(n_filters=64,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[pool2]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=96,
                   width=3,
                   height=3,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=96,
                   width=3,
                   height=3,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch3x3dbl = BN(act='relu')
        model.add(branch3x3dbl)

        # branch_pool
        model.add(
            Pooling(width=3,
                    height=3,
                    stride=1,
                    pool='average',
                    src_layers=[pool2]))
        model.add(
            Conv2d(n_filters=32,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch_pool = BN(act='relu')
        model.add(branch_pool)

        # mixed0 concat
        concat = Concat(
            act='identity',
            src_layers=[branch1x1, branch5x5, branch3x3dbl, branch_pool])
        model.add(concat)

        # mixed 1: output 35 x 35 x 288

        # branch1x1
        model.add(
            Conv2d(n_filters=64,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        branch1x1 = BN(act='relu')
        model.add(branch1x1)

        # branch5x5
        model.add(
            Conv2d(n_filters=48,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=64,
                   width=5,
                   height=5,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch5x5 = BN(act='relu')
        model.add(branch5x5)

        # branch3x3dbl
        model.add(
            Conv2d(n_filters=64,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=96,
                   width=3,
                   height=3,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=96,
                   width=3,
                   height=3,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch3x3dbl = BN(act='relu')
        model.add(branch3x3dbl)

        # branch_pool
        model.add(
            Pooling(width=3,
                    height=3,
                    stride=1,
                    pool='average',
                    src_layers=[concat]))
        model.add(
            Conv2d(n_filters=64,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch_pool = BN(act='relu')
        model.add(branch_pool)

        # mixed1 concat
        concat = Concat(
            act='identity',
            src_layers=[branch1x1, branch5x5, branch3x3dbl, branch_pool])
        model.add(concat)

        # mixed 2: output 35 x 35 x 288

        # branch1x1
        model.add(
            Conv2d(n_filters=64,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        branch1x1 = BN(act='relu')
        model.add(branch1x1)

        # branch5x5
        model.add(
            Conv2d(n_filters=48,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=64,
                   width=5,
                   height=5,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch5x5 = BN(act='relu')
        model.add(branch5x5)

        # branch3x3dbl
        model.add(
            Conv2d(n_filters=64,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=96,
                   width=3,
                   height=3,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=96,
                   width=3,
                   height=3,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch3x3dbl = BN(act='relu')
        model.add(branch3x3dbl)

        # branch_pool
        model.add(
            Pooling(width=3,
                    height=3,
                    stride=1,
                    pool='average',
                    src_layers=[concat]))
        model.add(
            Conv2d(n_filters=64,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch_pool = BN(act='relu')
        model.add(branch_pool)

        # mixed2 concat
        concat = Concat(
            act='identity',
            src_layers=[branch1x1, branch5x5, branch3x3dbl, branch_pool])
        model.add(concat)

        # mixed 3: output 17 x 17 x 768

        # branch3x3
        model.add(
            Conv2d(n_filters=384,
                   width=3,
                   height=3,
                   stride=2,
                   act='identity',
                   include_bias=False,
                   padding=0,
                   src_layers=[concat]))
        branch3x3 = BN(act='relu')
        model.add(branch3x3)

        # branch3x3dbl
        model.add(
            Conv2d(n_filters=64,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=96,
                   width=3,
                   height=3,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=96,
                   width=3,
                   height=3,
                   stride=2,
                   act='identity',
                   include_bias=False,
                   padding=0))
        branch3x3dbl = BN(act='relu')
        model.add(branch3x3dbl)

        # branch_pool
        branch_pool = Pooling(width=3,
                              height=3,
                              stride=2,
                              pool='max',
                              padding=0,
                              src_layers=[concat])
        model.add(branch_pool)

        # mixed3 concat
        concat = Concat(act='identity',
                        src_layers=[branch3x3, branch3x3dbl, branch_pool])
        model.add(concat)

        # mixed 4: output 17 x 17 x 768

        # branch1x1
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        branch1x1 = BN(act='relu')
        model.add(branch1x1)

        # branch7x7
        model.add(
            Conv2d(n_filters=128,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=128,
                   width=7,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=7,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch7x7 = BN(act='relu')
        model.add(branch7x7)

        # branch7x7dbl
        model.add(
            Conv2d(n_filters=128,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=128,
                   width=1,
                   height=7,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=128,
                   width=7,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=128,
                   width=1,
                   height=7,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=192,
                   width=7,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch7x7dbl = BN(act='relu')
        model.add(branch7x7dbl)

        # branch_pool
        model.add(
            Pooling(width=3,
                    height=3,
                    stride=1,
                    pool='average',
                    src_layers=[concat]))
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch_pool = BN(act='relu')
        model.add(branch_pool)

        # mixed4 concat
        concat = Concat(
            act='identity',
            src_layers=[branch1x1, branch7x7, branch7x7dbl, branch_pool])
        model.add(concat)

        # mixed 5, 6: output 17 x 17 x 768
        for i in range(2):
            # branch1x1
            model.add(
                Conv2d(n_filters=192,
                       width=1,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False,
                       src_layers=[concat]))
            branch1x1 = BN(act='relu')
            model.add(branch1x1)

            # branch7x7
            model.add(
                Conv2d(n_filters=160,
                       width=1,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False,
                       src_layers=[concat]))
            model.add(BN(act='relu'))
            model.add(
                Conv2d(n_filters=160,
                       width=7,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False))
            model.add(BN(act='relu'))
            model.add(
                Conv2d(n_filters=192,
                       width=1,
                       height=7,
                       stride=1,
                       act='identity',
                       include_bias=False))
            branch7x7 = BN(act='relu')
            model.add(branch7x7)

            # branch7x7dbl
            model.add(
                Conv2d(n_filters=160,
                       width=1,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False,
                       src_layers=[concat]))
            model.add(BN(act='relu'))
            model.add(
                Conv2d(n_filters=160,
                       width=1,
                       height=7,
                       stride=1,
                       act='identity',
                       include_bias=False))
            model.add(BN(act='relu'))
            model.add(
                Conv2d(n_filters=160,
                       width=7,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False))
            model.add(BN(act='relu'))
            model.add(
                Conv2d(n_filters=160,
                       width=1,
                       height=7,
                       stride=1,
                       act='identity',
                       include_bias=False))
            model.add(BN(act='relu'))
            model.add(
                Conv2d(n_filters=192,
                       width=7,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False))
            branch7x7dbl = BN(act='relu')
            model.add(branch7x7dbl)

            # branch_pool
            model.add(
                Pooling(width=3,
                        height=3,
                        stride=1,
                        pool='average',
                        src_layers=[concat]))
            model.add(
                Conv2d(n_filters=192,
                       width=1,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False))
            branch_pool = BN(act='relu')
            model.add(branch_pool)

            # concat
            concat = Concat(
                act='identity',
                src_layers=[branch1x1, branch7x7, branch7x7dbl, branch_pool])
            model.add(concat)

        # mixed 7: output 17 x 17 x 768

        # branch1x1
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        branch1x1 = BN(act='relu')
        model.add(branch1x1)

        # branch7x7
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=192,
                   width=7,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=7,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch7x7 = BN(act='relu')
        model.add(branch7x7)

        # branch7x7dbl
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=7,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=192,
                   width=7,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=7,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=192,
                   width=7,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch7x7dbl = BN(act='relu')
        model.add(branch7x7dbl)

        # branch_pool
        model.add(
            Pooling(width=3,
                    height=3,
                    stride=1,
                    pool='average',
                    src_layers=[concat]))
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False))
        branch_pool = BN(act='relu')
        model.add(branch_pool)

        # mixed7 concat
        concat = Concat(
            act='identity',
            src_layers=[branch1x1, branch7x7, branch7x7dbl, branch_pool])
        model.add(concat)

        # mixed 8: output 8 x 8 x 1280

        # branch3x3
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=320,
                   width=3,
                   height=3,
                   stride=2,
                   act='identity',
                   include_bias=False,
                   padding=0))
        branch3x3 = BN(act='relu')
        model.add(branch3x3)

        # branch7x7x3
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False,
                   src_layers=[concat]))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=192,
                   width=7,
                   height=1,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=192,
                   width=1,
                   height=7,
                   stride=1,
                   act='identity',
                   include_bias=False))
        model.add(BN(act='relu'))
        model.add(
            Conv2d(n_filters=192,
                   width=3,
                   height=3,
                   stride=2,
                   act='identity',
                   include_bias=False,
                   padding=0))
        branch7x7x3 = BN(act='relu')
        model.add(branch7x7x3)

        # branch_pool
        branch_pool = Pooling(width=3,
                              height=3,
                              stride=2,
                              pool='max',
                              padding=0,
                              src_layers=[concat])
        model.add(branch_pool)

        # mixed8 concat
        concat = Concat(act='identity',
                        src_layers=[branch3x3, branch7x7x3, branch_pool])
        model.add(concat)

        # mixed 9, 10:  output 8 x 8 x 2048
        for i in range(2):
            # branch1x1
            model.add(
                Conv2d(n_filters=320,
                       width=1,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False,
                       src_layers=[concat]))
            branch1x1 = BN(act='relu')
            model.add(branch1x1)

            # branch3x3
            model.add(
                Conv2d(n_filters=384,
                       width=1,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False,
                       src_layers=[concat]))
            branch3x3 = BN(act='relu')
            model.add(branch3x3)

            model.add(
                Conv2d(n_filters=384,
                       width=3,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False,
                       src_layers=[branch3x3]))
            branch3x3_1 = BN(act='relu')
            model.add(branch3x3_1)

            model.add(
                Conv2d(n_filters=384,
                       width=1,
                       height=3,
                       stride=1,
                       act='identity',
                       include_bias=False,
                       src_layers=[branch3x3]))
            branch3x3_2 = BN(act='relu')
            model.add(branch3x3_2)

            branch3x3 = Concat(act='identity',
                               src_layers=[branch3x3_1, branch3x3_2])
            model.add(branch3x3)

            # branch3x3dbl
            model.add(
                Conv2d(n_filters=448,
                       width=1,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False,
                       src_layers=[concat]))
            model.add(BN(act='relu'))
            model.add(
                Conv2d(n_filters=384,
                       width=3,
                       height=3,
                       stride=1,
                       act='identity',
                       include_bias=False))
            branch3x3dbl = BN(act='relu')
            model.add(branch3x3dbl)

            model.add(
                Conv2d(n_filters=384,
                       width=3,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False,
                       src_layers=[branch3x3dbl]))
            branch3x3dbl_1 = BN(act='relu')
            model.add(branch3x3dbl_1)

            model.add(
                Conv2d(n_filters=384,
                       width=1,
                       height=3,
                       stride=1,
                       act='identity',
                       include_bias=False,
                       src_layers=[branch3x3dbl]))
            branch3x3dbl_2 = BN(act='relu')
            model.add(branch3x3dbl_2)

            branch3x3dbl = Concat(act='identity',
                                  src_layers=[branch3x3dbl_1, branch3x3dbl_2])
            model.add(branch3x3dbl)

            # branch_pool
            model.add(
                Pooling(width=3,
                        height=3,
                        stride=1,
                        pool='average',
                        src_layers=[concat]))
            model.add(
                Conv2d(n_filters=192,
                       width=1,
                       height=1,
                       stride=1,
                       act='identity',
                       include_bias=False))
            branch_pool = BN(act='relu')
            model.add(branch_pool)

            # concat
            concat = Concat(
                act='identity',
                src_layers=[branch1x1, branch3x3, branch3x3dbl, branch_pool])
            model.add(concat)

        # calculate dimensions for global average pooling
        w = max((width - 75) // 32 + 1, 1)
        h = max((height - 75) // 32 + 1, 1)

        # global average pooling
        model.add(
            Pooling(width=w,
                    height=h,
                    stride=1,
                    pool='average',
                    padding=0,
                    src_layers=[concat]))

        # output layer
        model.add(OutputLayer(n=n_classes))

        return model

    else:
        if pre_trained_weights_file is None:
            raise ValueError(
                '\nThe pre-trained weights file is not specified.\n'
                'Please follow the steps below to attach the '
                'pre-trained weights:\n'
                '1. Go to the website '
                'https://support.sas.com/documentation/prod-p/vdmml/zip/ '
                'and download the associated weight file.\n'
                '2. Upload the *.h5 file to '
                'a server side directory which the CAS '
                'session has access to.\n'
                '3. Specify the pre_train_weight_file using '
                'the fully qualified server side path.')
        print('NOTE: Scale is set to 1/127.5, and offsets 1 to '
              'match Keras preprocessing.')
        model_cas = model_inceptionv3.InceptionV3_Model(
            s=conn,
            model_table=model_table,
            n_channels=n_channels,
            width=width,
            height=height,
            random_crop=random_crop,
            offsets=[1, 1, 1],
            random_flip=random_flip,
            random_mutation=random_mutation)

        if include_top:
            if n_classes != 1000:
                warnings.warn(
                    'If include_top = True, '
                    'n_classes will be set to 1000.', RuntimeWarning)
            model = Model.from_table(model_cas)
            model.load_weights(path=pre_trained_weights_file, labels=True)
            return model

        else:
            model = Model.from_table(model_cas, display_note=False)
            model.load_weights(path=pre_trained_weights_file)

            weight_table_options = model.model_weights.to_table_params()
            weight_table_options.update(dict(where='_LayerID_<218'))
            model._retrieve_('table.partition',
                             table=weight_table_options,
                             casout=dict(
                                 replace=True,
                                 **model.model_weights.to_table_params()))
            model._retrieve_('deeplearn.removelayer',
                             model=model_table,
                             name='predictions')
            model._retrieve_('deeplearn.addlayer',
                             model=model_table,
                             name='predictions',
                             layer=dict(type='output',
                                        n=n_classes,
                                        act='softmax'),
                             srcLayers=['avg_pool'])
            model = Model.from_table(conn.CASTable(model_table))

            return model