예제 #1
0
 def test_raise_conv_multi_src(self):
     with self.assertRaises(DLPyError):
         inputs = Input(3, 512, 512, scale=1.0 / 255, name='input1')
         conv1 = Conv2d(8, 3, act='relu')(inputs)
         conv2 = Conv2d(8, 3, act='relu')(inputs)
         conv3 = Conv2d(8, 3)([conv1, conv2])
         output1 = OutputLayer(name='output1')(conv3)
         model = Model(self.s, inputs=inputs, outputs=output1)
         model.compile()
예제 #2
0
 def test_multi_src_layer_fc(self):
     inputs = Input(1, 28, 28, scale=1.0 / 255, name='InputLayer_1')
     fc1 = Dense(n=128, name='dense1')(inputs)
     fc2 = Dense(n=64, name='dense2')(fc1)
     fc3 = Dense(n=64, name='dense3')([fc1, fc2])
     output1 = OutputLayer(n=10, name='OutputLayer_1')(fc3)
     model = Model(self.s, inputs=inputs, outputs=output1)
     model.compile()
     self.assertTrue(model.count_params() == 117386)
예제 #3
0
    def test_submodel_as_inputs_network(self):
        inputs1 = Input(1, 53, 53, scale=1.0 / 255, name='InputLayer_1')
        # inputs2 = InputLayer(1, 28, 28, scale = 1.0 / 255, name = 'InputLayer_2')
        dense1 = Dense(10, name='d1')(inputs1)
        dense2 = Dense(12, name='d2')(dense1)
        dense3 = Dense(n=128, name='d3')(dense2)
        model_dense = Model(self.s, inputs=inputs1, outputs=dense3)

        inputs2 = Input(1, 53, 53, scale=1.0 / 255, name='InputLayer_2')
        # inputs2 = InputLayer(1, 28, 28, scale = 1.0 / 255, name = 'InputLayer_2')
        dense4 = Dense(10, name='d4')(inputs2)
        dense5 = Dense(12, name='d5')(dense4)
        dense6 = Dense(n=128, name='d6')(dense5)
        model_dense2 = Model(self.s, inputs=inputs2, outputs=dense6)

        inputs3 = Input(1, 53, 53, scale=1.0 / 255, name='InputLayer_3')
        inputs4 = Input(1, 53, 53, scale=1.0 / 255, name='InputLayer_4')
        out3 = model_dense(inputs3)
        out4 = model_dense2(inputs4)

        out5 = [out4[0], out3[0]]

        concat1 = Dense(20, name='d7')(out5)
        output1 = OutputLayer(n=10, name='OutputLayer_1')(concat1)
        model = Model(self.s, inputs=[inputs3, inputs4], outputs=output1)
        model.compile()
        model.print_summary()
        self.assertTrue(model.count_params() == 62262)
예제 #4
0
 def test_load_reshape_detection(self):
     if self.data_dir is None:
         unittest.TestCase.skipTest(self, "DLPY_DATA_DIR is not set in the environment variables")
     yolo_model = Model(self.s)
     yolo_model.load(self.data_dir + 'YOLOV2_MULTISIZE.sashdat')
     model_df = self.s.fetch(table = dict(name = yolo_model.model_name,
                                          where = '_DLKey0_ eq "detection1" or _DLKey0_ eq "reshape1"'), to = 50).Fetch
     anchors_5 = model_df['_DLNumVal_'][model_df['_DLKey1_'] == 'detectionopts.anchors.8'].tolist()[0]
     self.assertAlmostEqual(anchors_5, 1.0907, 4)
     depth = model_df['_DLNumVal_'][model_df['_DLKey1_'] == 'reshapeopts.depth'].tolist()[0]
     self.assertEqual(depth, 256)
예제 #5
0
    def test_submodel_multiple_inputs_network(self):
        inputs1 = Input(1, 53, 53, scale=1.0 / 255, name='InputLayer_1')
        # inputs2 = InputLayer(1, 28, 28, scale = 1.0 / 255, name = 'InputLayer_2')
        dense1 = Dense(10, name='d1')(inputs1)
        dense2 = Dense(12, name='d2')(dense1)
        dense3 = Dense(n=128, name='d3')(dense2)
        # model_dense = Model(self.s, inputs=inputs1, outputs= dense3)

        inputs2 = Input(1, 53, 53, scale=1.0 / 255, name='InputLayer_2')
        # inputs2 = InputLayer(1, 28, 28, scale = 1.0 / 255, name = 'InputLayer_2')
        dense4 = Dense(10, name='d4')(inputs2)
        dense5 = Dense(12, name='d5')(dense4)
        dense6 = Dense(n=128, name='d6')(dense5)
        dense7 = Dense(n=190, name='cat1')([dense3, dense6])
        model_dense = Model(self.s,
                            inputs=[inputs1, inputs2],
                            outputs=[dense7])

        input3 = Input(1, 53, 53, scale=1.0 / 255, name='InputLayer_3')
        input4 = Input(1, 53, 53, scale=1.0 / 255, name='InputLayer_4')

        out = model_dense([input3, input4])

        dense7 = Dense(20, name='d7')(out)
        output1 = OutputLayer(n=10, name='OutputLayer_1')(dense7)
        model = Model(self.s, inputs=[input3, input4], outputs=output1)
        model.compile()
        model.print_summary()
        self.assertTrue(model.count_params() == 87822)
예제 #6
0
 def test_extract_clustering1(self):
     model = Sequential(self.s, model_table = 'Simple_CNN')
     model.add(InputLayer(3, 48, 96, scale = 1.0 / 255, random_mutation = 'none'))
     model.add(Split(16))
     model.add(Clustering(n_clusters=10))
     model_extracted = Model.from_table(self.s.CASTable(model.model_table['name']))
     model_extracted.compile()
예제 #7
0
    def test_mobilenetv2(self):
        try:
            import onnx
            from dlpy.model_conversion.onnx_transforms import (Transformer, OpTypePattern,
                                                               ConstToInitializer,
                                                               InitReshape, InitUnsqueeze,
                                                               FuseMulAddBN)
            from dlpy.model_conversion.onnx_graph import OnnxGraph
            from onnx import helper, numpy_helper
        except:
            unittest.TestCase.skipTest(self, 'onnx package not found')

        from dlpy.model import Model

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


        path = os.path.join(self.data_dir_local, 'mobilenetv2-1.0.onnx')

        onnx_model = onnx.load_model(path)
        model1 = Model.from_onnx_model(self.s,
                                       onnx_model,
                                       output_model_table='mobilenetv2',
                                       offsets=255*[0.485, 0.456, 0.406],
                                       norm_stds=255*[0.229, 0.224, 0.225])
예제 #8
0
    def test_model29(self):
        # test specifying output layer in Model.from_onnx_model
        try:
            import onnx
        except:
            unittest.TestCase.skipTest(self, "onnx not found in the libraries")

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

        m = onnx.load(os.path.join(self.data_dir_local, 'Simple_CNN1.onnx'))
        output_layer = OutputLayer(n=100)
        model1 = Model.from_onnx_model(conn=self.s,
                                       onnx_model=m,
                                       offsets=[
                                           1,
                                           1,
                                           1,
                                       ],
                                       scale=2,
                                       std='std',
                                       output_layer=output_layer)

        self.assertTrue(model1.layers[-1].config['n'] == 100)
예제 #9
0
 def test_extract_embeddingloss1(self):
     model = Sequential(self.s, model_table = 'Simple_CNN')
     model.add(InputLayer(3, 48, 96, scale = 1.0 / 255, random_mutation = 'none'))
     model.add(Dense(16))
     model.add(EmbeddingLoss(margin=10))
     model_extracted = Model.from_table(self.s.CASTable(model.model_table['name']))
     model_extracted.compile()
     self.assertTrue(model_extracted.layers[-1].config['margin'] == 10)
예제 #10
0
    def load_acoustic_model(self, acoustic_model_path):
        """
        Load the RNN acoustic model.

        Parameters
        ----------
        acoustic_model_path : string
            Specifies the absolute server-side path of the acoustic model file.
            Please make sure the weights file and the weights attribute file are placed under the same directory.

        """
        self.acoustic_model = Model(self.conn)
        self.acoustic_model.from_sashdat(self.conn, path=acoustic_model_path)
        if self.acoustic_model.model_table is None:
            raise DLPyError("Failed to load the acoustic model.")
        if self.acoustic_model.model_weights is None:
            raise DLPyError("Failed to load the acoustic model weights.")
예제 #11
0
    def test_resnet(self):
        def conv_block(x, filters, size, stride = 1, mode = 'same', act = True):
            x = Conv2d(filters, size, size, act = 'identity', include_bias = False, stride = stride)(x)
            x = BN(act = 'relu' if act else 'identity')(x)
            return x

        def res_block(ip, nf = 64):
            x = conv_block(ip, nf, 3, 1)
            x = conv_block(x, nf, 3, 1, act = False)
            return Res()([x, ip])

        inp = Input(1, 32, 32, scale = 1.0 / 255, name = 'InputLayer_1')
        x = conv_block(inp, 64, 9, 1)
        for i in range(1): x = res_block(x)
        x = Conv2d(1, 9, 9, act = 'tanh')(x)
        output = OutputLayer(n = 100)(x)
        model = Model(self.s, inputs = inp, outputs = output)
        model.compile()
예제 #12
0
 def test_extract_segmentation1(self):
     model = Sequential(self.s, model_table = 'Simple_CNN')
     model.add(InputLayer(3, 48, 96, scale = 1.0 / 255, random_mutation = 'none'))
     model.add(Dense(16))
     model.add(Segmentation(act='AUTO', target_scale=10))
     model_extracted = Model.from_table(self.s.CASTable(model.model_table['name']))
     model_extracted.compile()
     self.assertTrue(model_extracted.layers[-1].config['act'] == 'AUTO')
     self.assertTrue(model_extracted.layers[-1].config['target_scale'] == 10)
예제 #13
0
 def test_without_variable(self):
     input1 = Input(n_channels=1, width=28, height=28)
     conv1 = Conv2d(2)(Conv2d(2)(input1))
     output1 = OutputLayer(n=2)(conv1)
     model1 = Model(conn=self.s, inputs=[input1], outputs=[output1])
     model1.compile()
     model1.print_summary()
     self.assertTrue(model1.count_params() == 3196)
예제 #14
0
    def __init__(self, conn, layers=None, model_table=None):
        Model.__init__(self, conn, model_table=model_table)

        if layers is None:
            self.layers = []
            self.layers_dict = {}
        elif type(layers) is list or type(layers) is set or type(
                layers) is tuple:
            self.layers = layers
            for layer in self.layers:
                if layer.name is not None:
                    self.layers_dict[layer.name] = layer
            if len(layers) > 0 and isinstance(
                    layers[-1], Layer) and layers[-1].can_be_last_layer:
                self.compile()
            else:
                raise DLPyError('layers has to be a list of layer(s).')
        else:
            raise DLPyError('layers has to be a list of layer(s).')
예제 #15
0
 def test_non_list_src_layers(self):
     inputs = Input(1, 28, 28, scale=1.0 / 255, name='InputLayer_1')
     fc1 = Dense(n=128)(inputs)
     fc2 = Dense(n=64)(fc1)
     output1 = OutputLayer(n=10, name='OutputLayer_1')([fc1, fc2])
     model = Model(self.s, inputs=inputs, outputs=output1)
     model.compile()
     model.print_summary()
     self.assertTrue(model.count_params() == 109834)
예제 #16
0
    def test_imagescaler1(self):
        # test import model with imagescaler
        try:
            import onnx
            from onnx import helper, TensorProto
        except:
            unittest.TestCase.skipTest(self, 'onnx not found')

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

        import numpy as np
        n1 = helper.make_node('ImageScaler', ['X'], ['X1'],
                              bias=[0., 0., 0.],
                              scale=1.)
        n2 = helper.make_node('Conv',
                              inputs=['X1', 'W1'],
                              outputs=['X2'],
                              kernel_shape=[3, 3],
                              pads=[0, 0, 0, 0])
        n3 = helper.make_node('MatMul', inputs=['X2', 'W2'], outputs=['X3'])

        W1 = np.ones((3, 3, 3)).astype(np.float32)
        W2 = np.ones((9, 2)).astype(np.float32)

        graph_def = helper.make_graph(
            [n1, n2, n3],
            name='test',
            inputs=[
                helper.make_tensor_value_info('X', TensorProto.FLOAT,
                                              [1, 3, 10, 10]),
                helper.make_tensor_value_info('W1', TensorProto.FLOAT,
                                              [3, 3, 3]),
                helper.make_tensor_value_info('W2', TensorProto.FLOAT, [9, 2])
            ],
            outputs=[
                helper.make_tensor_value_info('X3', TensorProto.FLOAT, [1, 2])
            ],
            initializer=[
                helper.make_tensor('W1', TensorProto.FLOAT, [3, 3, 3],
                                   W1.flatten().astype(np.float32)),
                helper.make_tensor('W2', TensorProto.FLOAT, [9, 2],
                                   W2.flatten().astype(np.float32))
            ])
        onnx_model = helper.make_model(graph_def)

        model1 = Model.from_onnx_model(self.s, onnx_model)

        l1 = model1.layers[0]
        self.assertTrue(l1.type == 'input')
        self.assertTrue(l1.config['offsets'] == [0., 0., 0.])
        self.assertTrue(l1.config['scale'] == 1.)
예제 #17
0
    def test_model6(self):
        try:
            import onnx
        except:
            unittest.TestCase.skipTest(self, "onnx not found in the libraries")

        m = onnx.load(
            os.path.join(os.path.dirname(__file__), 'datasources',
                         'model.onnx'))
        model1 = Model.from_onnx_model(self.s, m)
        model1.print_summary()
예제 #18
0
    def test_outputs(self):
        with self.assertRaises(DLPyError):
            input1 = InputLayer(n_channels=1, width=28, height=28)
            conv1 = Conv2d(2)(input1)
            model1 = Model(conn=self.s, inputs=[input1], outputs=[conv1])
            model1.compile()

        with self.assertRaises(DLPyError):
            input1 = InputLayer(n_channels=1, width=28, height=28)
            conv1 = Conv2d(2)(input1)
            conv2 = BN()(input1)
            output1 = OutputLayer(2)(conv1)
            model1 = Model(conn=self.s, inputs=[input1], outputs=[conv2, output1])
            model1.compile()
예제 #19
0
    def test_model28(self):
        try:
            import onnx
        except:
            unittest.TestCase.skipTest(self, "onnx not found in the libraries")

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

        m = onnx.load(os.path.join(self.data_dir_local, 'pytorch_net2.onnx'))
        model1 = Model.from_onnx_model(self.s, m, offsets=[1, 1, 1,], scale=2, std='std')
        model1.print_summary()
예제 #20
0
 def test_concat(self):
     input1 = Input(n_channels=1, width=28, height=28)
     input2 = Input(n_channels=3, width=28, height=28)
     conv1 = Conv2d(2)(input1)
     conv2 = Conv2d(2)(input1)
     conv3 = Conv2d(2)(input2)
     output2 = OutputLayer(n=2)(conv3)
     concat1 = Concat()([conv1, conv2, conv3])
     output1 = OutputLayer(n=2)(concat1)
     model1 = Model(conn=self.s, inputs=[input1, input2], outputs=[output1, output2])
     model1.compile()
     model1.print_summary()
     self.assertTrue(model1.count_params() == 12644)
예제 #21
0
    def test_submodel_in_middle_network(self):
        inputs1 = Input(1, 53, 53, scale=1.0 / 255, name='InputLayer_1')
        inputs2 = Input(1, 28, 28, scale=1.0 / 255, name='InputLayer_2')
        dense1 = Dense(10, name='d1')(inputs2)
        dense2 = Dense(12, name='d2')(dense1)
        dense3 = Dense(n=128, name='d3')(dense2)
        model_dense = Model(self.s, inputs=inputs2, outputs=dense3)

        fore = model_dense(inputs1)

        concat1 = Dense(20, name='d7')(fore)
        output1 = OutputLayer(n=10, name='OutputLayer_1')(concat1)

        model = Model(self.s, inputs=[inputs1], outputs=output1)
        model.compile()
        model.print_summary()
        self.assertTrue(model.count_params() == 32516)
예제 #22
0
    def test_submodel_as_input_network(self):
        inputs1 = Input(1, 53, 53, scale=1.0 / 255, name='InputLayer_1')
        # inputs2 = InputLayer(1, 28, 28, scale = 1.0 / 255, name = 'InputLayer_2')
        dense1 = Dense(10, name='dense1')(inputs1)
        dense2 = Dense(12, name='dense2')(dense1)
        dense3 = Dense(n=128, name='dense3')(dense2)
        model_dense = Model(self.s, inputs=inputs1, outputs=dense3)

        inputs2 = Input(1, 53, 53, scale=1.0 / 255, name='InputLayer_2')
        out_submodel = model_dense(inputs2)

        concat1 = Dense(20, 'concat1')(out_submodel)
        output1 = OutputLayer(n=10, name='OutputLayer_1')(concat1)
        model = Model(self.s, inputs=[inputs2], outputs=output1)
        model.compile()
        model.print_summary()
        self.assertTrue(model.count_params() == 32516)
예제 #23
0
 def test_given_name(self):
     inputs = Input(3, 512, 512, scale=1.0 / 255, name='input1')
     conv1 = Conv2d(8, 3, act='relu')(inputs)
     conv2 = Conv2d(8, 3, act='relu')(inputs)
     merge3 = Concat()([conv1, conv2])
     conv3 = Conv2d(3, 3, act='relu')(merge3)
     output1 = OutputLayer(name='output1')(conv3)
     model = Model(self.s, inputs=inputs, outputs=output1)
     model.compile()
     self.assertTrue(inputs._op.name == 'input1')
     self.assertTrue(output1._op.name == 'output1')
     model.print_summary()
예제 #24
0
 def test_residual_output_shape0(self):
     inLayer = Input(n_channels = 3, width = 32, height = 128,
                     name = 'input1', random_mutation = 'random', random_flip = 'HV')
     conv1 = Conv2d(32, 3, 3, name = 'conv1', act = 'relu', init = 'msra')([inLayer])
     conv2 = Conv2d(32, 5, 5, name = 'conv2', act = 'relu', init = 'msra')([inLayer])
     fc1 = Dense(3, name = 'fc1')([conv1])
     fc2 = Dense(3, name = 'fc2')([conv2])
     res = Res(name = 'res1')([fc1, fc2])
     outLayer = OutputLayer(n = 3, name = 'output')([res])
     model = Model(self.s, inLayer, outLayer)
     model.compile()
     self.assertEqual(model.summary['Output Size'].values[-2], 3)
     model.print_summary()
예제 #25
0
    def test_model10(self):
        try:
            import onnx
        except:
            unittest.TestCase.skipTest(self, "onnx not found in the libraries")

        m = onnx.load(
            os.path.join(os.path.dirname(__file__), 'datasources',
                         'pytorch_net2.onnx'))
        model1 = Model.from_onnx_model(self.s,
                                       m,
                                       offsets=[
                                           1,
                                           1,
                                           1,
                                       ],
                                       scale=2,
                                       std='std')
        model1.print_summary()
예제 #26
0
    def test_stop_layers(self):
        from dlpy.sequential import Sequential
        model1 = Sequential(self.s)
        model1.add(InputLayer(3, 224, 224))
        model1.add(Conv2d(8, 7))
        model1.add(Pooling(2))
        model1.add(Conv2d(8, 7))
        model1.add(Pooling(2))
        model1.add(Dense(16))
        model1.add(OutputLayer(act = 'softmax', n = 2))

        inputlayer = model1.layers[0]
        inp = Input(**inputlayer.config)
        func_model = model1.to_functional_model(stop_layers = [model1.layers[-1]])
        x = func_model(inp)
        out = Keypoints(n=10)(x)
        func_model_keypoints = Model(self.s, inp, out)
        func_model_keypoints.compile()
        func_model_keypoints.print_summary()
예제 #27
0
def MobileNetV2_ONNX(conn,
                     model_file,
                     n_classes=1000,
                     width=224,
                     height=224,
                     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,
                     include_top=False):
    """
    Generates a deep learning model with the MobileNetV2_ONNX architecture.
    The model architecture and pre-trained weights is generated from MobileNetV2 ONNX trained on ImageNet dataset.
    The model file and the weights file can be downloaded from https://support.sas.com/documentation/prod-p/vdmml/zip/.
    To learn more information about the model and pre-processing.
    Please go to the websites: https://github.com/onnx/models/tree/master/vision/classification/mobilenet.

    Parameters
    ----------
    conn : CAS
        Specifies the CAS connection object.
    model_file : string
        Specifies the absolute server-side path of the model table file.
        The model table file can be downloaded from https://support.sas.com/documentation/prod-p/vdmml/zip/.
    n_classes : int, optional
        Specifies the number of classes.
        Default: 1000
    width : int, optional
        Specifies the width of the input layer.
        Default: 224
    height : int, optional
        Specifies the height of the input layer.
        Default: 224
    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.
        The channel order is BGR.
        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.
        The channel order is BGR.
        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'
    include_top : bool, optional
        Specifies whether to include pre-trained weights of the top layers (i.e., the FC layers)
        Default: False

    """
    parameters = locals()
    input_parameters = get_layer_options(input_layer_options, parameters)

    # load model and model weights
    model = Model.from_sashdat(conn, path=model_file)
    # check if a user points to a correct model.
    if model.summary.shape[0] != 120:
        raise DLPyError(
            "The model file doesn't point to a valid MobileNetV2_ONNX model. "
            "Please check the SASHDAT file.")
    # extract input layer config
    model_table_df = conn.CASTable(**model.model_table).to_frame()
    input_layer_df = model_table_df[model_table_df['_DLLayerID_'] == 0]
    input_layer = extract_input_layer(input_layer_df)
    input_layer_config = input_layer.config
    # update input layer config
    input_layer_config.update(input_parameters)
    # update the layer list
    model.layers[0] = InputLayer(**input_layer_config,
                                 name=model.layers[0].name)

    # warning if model weights doesn't exist
    if not conn.tableexists(model.model_weights.name).exists:
        weights_file_path = os.path.join(os.path.dirname(model_file),
                                         model.model_name + '_weights.sashdat')
        print('WARNING: Model weights is not attached '
              'since system cannot find a weights file located at {}'.format(
                  weights_file_path))

    if include_top:
        if n_classes != 1000:
            raise DLPyError(
                "If include_top is enabled, n_classes has to be 1000.")
    else:
        # since the output layer is non fully connected layer,
        # we need to modify the convolution right before the output. The number of filter is set to n_classes.
        conv_layer_df = model_table_df[model_table_df['_DLLayerID_'] == 118]
        conv_layer = extract_conv_layer(conv_layer_df)
        conv_layer_config = conv_layer.config
        # update input layer config
        conv_layer_config.update({'n_filters': n_classes})
        # update the layer list
        model.layers[-2] = Conv2d(**conv_layer_config,
                                  name=model.layers[-2].name,
                                  src_layers=model.layers[-3])

        # overwrite n_classes in output layer
        out_layer_df = model_table_df[model_table_df['_DLLayerID_'] == 119]
        out_layer = extract_output_layer(out_layer_df)
        out_layer_config = out_layer.config
        # update input layer config
        out_layer_config.update({'n': n_classes})
        # update the layer list
        model.layers[-1] = OutputLayer(**out_layer_config,
                                       name=model.layers[-1].name,
                                       src_layers=model.layers[-2])

        # remove top weights
        model.model_weights.append_where('_LayerID_<118')
        model._retrieve_('table.partition',
                         table=model.model_weights,
                         casout=dict(replace=True,
                                     name=model.model_weights.name))
        model.set_weights(model.model_weights.name)
    # recompile the whole network according to the new layer list
    model.compile()
    return model
예제 #28
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
예제 #29
0
def MobileNetV1(conn,
                model_table='MobileNetV1',
                n_classes=1000,
                n_channels=3,
                width=224,
                height=224,
                random_flip=None,
                random_crop=None,
                random_mutation=None,
                norm_stds=(255 * 0.229, 255 * 0.224, 255 * 0.225),
                offsets=(255 * 0.485, 255 * 0.456, 255 * 0.406),
                alpha=1,
                depth_multiplier=1):
    '''
    Generates a deep learning model with the MobileNetV1 architecture.
    The implementation is revised based on
    https://github.com/keras-team/keras-applications/blob/master/keras_applications/mobilenet.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
    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'
    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)
    alpha : int, optional
        Specifies the width multiplier in the MobileNet paper
        Default: 1
    depth_multiplier : int, optional
        Specifies the number of depthwise convolution output channels for each input channel.
        Default: 1

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

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

    '''
    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

    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

    parameters = locals()
    input_parameters = get_layer_options(input_layer_options, parameters)
    inp = Input(**input_parameters, name='data')
    # the model down-sampled for 5 times by performing stride=2 convolution on
    # conv_dw_1, conv_dw_2, conv_dw_4, conv_dw_6, conv_dw_12
    # for each block, we use depthwise convolution with kernel=3 and point-wise convolution to save computation
    x, depth = _conv_block(inp, 32, alpha, stride=2)
    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     64,
                                     alpha,
                                     depth_multiplier,
                                     block_id=1)

    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     128,
                                     alpha,
                                     depth_multiplier,
                                     stride=2,
                                     block_id=2)
    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     128,
                                     alpha,
                                     depth_multiplier,
                                     block_id=3)

    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     256,
                                     alpha,
                                     depth_multiplier,
                                     stride=2,
                                     block_id=4)
    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     256,
                                     alpha,
                                     depth_multiplier,
                                     block_id=5)

    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     512,
                                     alpha,
                                     depth_multiplier,
                                     stride=2,
                                     block_id=6)
    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     512,
                                     alpha,
                                     depth_multiplier,
                                     block_id=7)
    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     512,
                                     alpha,
                                     depth_multiplier,
                                     block_id=8)
    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     512,
                                     alpha,
                                     depth_multiplier,
                                     block_id=9)
    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     512,
                                     alpha,
                                     depth_multiplier,
                                     block_id=10)
    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     512,
                                     alpha,
                                     depth_multiplier,
                                     block_id=11)

    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     1024,
                                     alpha,
                                     depth_multiplier,
                                     stride=2,
                                     block_id=12)
    x, depth = _depthwise_conv_block(x,
                                     depth,
                                     1024,
                                     alpha,
                                     depth_multiplier,
                                     block_id=13)

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

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

    return model
예제 #30
0
 def test_inputs(self):
     conv1 = Conv2d(2)
     with self.assertRaises(ValueError):
         output1 = OutputLayer(2)(conv1)
         Model(conn=self.s, inputs=[conv1], outputs=[output1])