Пример #1
0
def apply_transformations(in_model):
    src_model = None
    src_model_config = in_model.get_config()
    k = 1024
    for info_txt, check_func, apply_func in zip(info_list[:k], check_transform_list[:k], apply_transform_list[:k]):
        if check_func(src_model_config):
            if src_model is None:
                print('Preparation for the transformation...\n')
                src_model = Model.from_config(in_model.get_config(), custom_objects=extra_custom_objects)
                transfer_weights(in_model, src_model, {})
                check_transform(in_model, src_model)

            print(info_txt)
            src_model_config = src_model.get_config()
            dst_model_config, weight_transfer_rule_dict = apply_func(src_model_config)
            dst_model = Model.from_config(dst_model_config, custom_objects=extra_custom_objects)
            transfer_weights(src_model, dst_model, weight_transfer_rule_dict)
            check_transform(in_model, dst_model)

            del src_model
            src_model = dst_model
        else:
            print(f'Nothing to do with {info_txt.split(":")[0]} transform\n')

    if src_model is None:
        return in_model

    return src_model
Пример #2
0
def create_dropout_predict_function(model, dropout):
    """
    Hard-codes a dropout rate to the Dropout layers of a trained model.
    When initially training model, Dropout layers must have training=True, 
    otherwise dropout will not be applied to predictions.

    Parameters:
        model : trained keras model
        dropout : dropout rate to apply to all Dropout layers
    
    Returns:
        predict_with_dropout : keras model that will apply dropout when making predictions
    """
    
    # Load the config of the original model
    conf = model.get_config()
    # Add the specified dropout to all layers
    for layer in conf['layers']:
        # Dropout layers
        if layer["class_name"]=="Dropout":
            layer["config"]["rate"] = dropout
        # Recurrent layers with dropout
        elif "dropout" in layer["config"].keys():
            layer["config"]["dropout"] = dropout

    # Create a new model with specified dropout
    if type(model)==Sequential:
        # Sequential
        model_dropout = Sequential.from_config(conf)
    else:
        # Functional
        model_dropout = Model.from_config(conf)
    model_dropout.set_weights(model.get_weights())
    
    return model_dropout
Пример #3
0
 def from_config(cls, config, custom_objects={}):
     if type(custom_objects) is list:
         custom_objects = {obj.__name__: obj for obj in custom_objects}
     custom_objects.update(_get_cells())
     model_config = config.pop('model_config')
     model = Model.from_config(model_config, custom_objects)
     return cls(model, **config)
Пример #4
0
def split(model, start, end):
    confs = model.get_config()
    kept_layers = set()
    for i, l in enumerate(confs['layers']):
        if i == 0:
            confs['layers'][0]['config']['batch_input_shape'] = model.layers[
                start].input_shape
            if i != start:
                # confs['layers'][0]['name'] += str(random.randint(0, 100000000))
                confs['layers'][0]['config']['name'] = confs['layers'][0][
                    'name']
        elif i < start or i > end:
            continue
        kept_layers.add(l['name'])
    # filter layers
    layers = [l for l in confs['layers'] if l['name'] in kept_layers]
    layers[1]['inbound_nodes'][0][0][0] = layers[0]['name']
    # set conf
    confs['layers'] = layers
    confs['input_layers'][0][0] = layers[0]['name']
    confs['output_layers'][0][0] = layers[-1]['name']
    # create new model
    submodel = Model.from_config(confs)
    for l in submodel.layers:
        orig_l = model.get_layer(l.name)
        if orig_l is not None:
            l.set_weights(orig_l.get_weights())
    return submodel
Пример #5
0
def adapt_keras_model(keras_model, model_name):
    keras_model_config = keras_model.get_config()
    keras_model_config['name'] = model_name
    # assert len(keras_model_config['input_layers']) == len(
    #     keras_model_config['output_layers']) == 1, 'Multi IN/OUT is not supported'
    if len(keras_model_config['output_layers']) != 1:
        print("WARNING :: Multi Output Detected!!!")
    if is_multi_output(keras_model_config):
        adapted_model_config = split_output_nodes(keras_model_config)
        # adapted_model_config = rename_layer(adapted_model_config, keras_model_config['input_layers'][0][0], 'data')
        # adapted_model_config = rename_layer(adapted_model_config, keras_model_config['output_layers'][0][0], 'output')
        adapted_keras_model = Model.from_config(
            adapted_model_config, custom_objects=extra_custom_objects)
    else:
        adapted_keras_model = Model.from_config(
            keras_model_config, custom_objects=extra_custom_objects)
    adapted_keras_model.set_weights(keras_model.get_weights())
    return adapted_keras_model
Пример #6
0
def make_predictions(model, weights, test_gen, lr):
    config = model.get_config()
    pmodel = Model.from_config(config)  # copy of the model
    pmodel.set_weights(
        weights)  #load saved weights with lowest validation loss
    pmodel.compile(Adam(lr=lr),
                   loss='categorical_crossentropy',
                   metrics=['accuracy'])
    print(
        'Training has completed. Now loading test set to see how accurate the model is'
    )
    results = pmodel.evaluate(test_gen, verbose=0)
    print('Model accuracy on Test Set is {0:7.2f} %'.format(results[1] * 100))
    predictions = pmodel.predict(test_gen, verbose=0)
    return predictions
Пример #7
0
def deepspam_load(path="model"):
    global wordmap
    global model
    print('Loading Model...')
    config=json.load(open(path+"/model.config","rt"))
    model = Model.from_config(config)
    model.load_weights(path+"/model.weights")
####weights=pickle.load(open("model.weights", "rb"))
#model.set_weights(weights)
    try:
        wordmap=pickle.load(open(path+"/model.wordmap-py3", "rb"))
    except:
        wordmap=pickle.load(open(path+"/model.wordmap-py2", "rb"))
#wordmap=[]
    print("MODEL loaded! (%d words)"%(len(wordmap)))
    return wordmap
Пример #8
0
    def reset_pingpong(self):
        """ Reset the models for pingpong training """
        logger.debug("Resetting models")

        # Clear models and graph
        self.predictors = dict()
        K.clear_session()

        # Load Models for current training run
        for model in self.networks.values():
            model.network = Model.from_config(model.config)
            model.network.set_weights(model.weights)

        inputs = self.get_inputs()
        self.build_autoencoders(inputs)
        self.compile_predictors(initialize=False)
        logger.debug("Reset models")
Пример #9
0
def deepspam_load(path="model"):
    global wordmap
    global model

    #    global tf_session
    #    print('Creating TF session...')
    #    config = tensorflow.ConfigProto(
    #                intra_op_parallelism_threads=1,
    #                allow_soft_placement=True
    #            )
    #    tf_session = tensorflow.Session(config=config)
    #    tensorflow.set_session(tf_session)

    global tf_session
    global tf_graph

    print('Loading Model...')
    config = json.load(open(path + "/model.config", "rt"))
    model = Model.from_config(config)
    model.load_weights(path + "/model.weights")
    ####weights=pickle.load(open("model.weights", "rb"))
    #model.set_weights(weights)
    try:
        wordmap = pickle.load(open(path + "/model.wordmap-py3", "rb"))
    except:
        wordmap = pickle.load(open(path + "/model.wordmap-py2", "rb"))


#wordmap=[]
    print("MODEL loaded! (%d words)" % (len(wordmap)))

    # testing
    data = np.zeros((1, MAX_SEQUENCE_LENGTH), dtype='int32')
    classes = model.predict(data, batch_size=1, verbose=1)

    tf_session = K.get_session()
    tf_graph = tensorflow.get_default_graph()
    tf_graph.finalize()
    print("MODEL finalized!")

    return wordmap
Пример #10
0
 def from_config(cls, config, custom_objects={}):
     if type(custom_objects) is list:
         custom_objects = {obj.__name__: obj for obj in custom_objects}
     custom_objects.update(_get_cells())
     config = config.copy()
     model_config = config.pop('model_config')
     if model_config is None:
         model = None
     else:
         model = Model.from_config(model_config, custom_objects)
     if type(model.input) is list:
         input = model.input[0]
         initial_states = model.input[1:]
     else:
         input = model.input
         initial_states = None
     if type(model.output) is list:
         output = model.output[0]
         final_states = model.output[1:]
     else:
         output = model.output
         final_states = None
     return cls(input, output, initial_states, final_states, **config)
Пример #11
0
def deepspam_worker(q, path):
    print('Loading Model...')
    config = json.load(open(path + "/model.config", "rt"))
    model = Model.from_config(config)
    model.load_weights(path + "/model.weights")
    ####weights=pickle.load(open("model.weights", "rb"))
    #model.set_weights(weights)
    #wordmap=[]
    #    print("MODEL loaded! (%d words)"%(len(wordmap)))
    print("worker: started!!!")
    while True:
        dprint("worker: waiting for job... (%d)" % (q.qsize()))
        data, retq = q.get()
        if not retq:
            break
        dprint("worker: new job!")
        classes = model.predict(data, batch_size=1, verbose=1)
        res = classes[0][0] * 100.0 / (classes[0][0] + classes[0][1])
        dprint("worker: result=" + str(res))
        retq.put(res)
        q.task_done()
    print("worker: exiting!!!")
    q.task_done()
# ============================================================== #

optimizer = tf.keras.optimizers.Adam(lr=LEARNING_RATE)
optimizer = tf.keras.mixed_precision.experimental.LossScaleOptimizer(
    opt=optimizer, loss_scale=loss_scaler)

print('Optimizer Configuration:')

print('\nOptimizer `get_slot_names()`: %s\n' % str(optimizer.get_slot_names()))

autoencoder = Model(inputs, decoded)
autoencoder.compile(optimizer=optimizer, loss='mae', metrics=['mae'])

# ============ Test Model Recreation from config ============ #
model_config = autoencoder.get_config()
autoencoder = Model.from_config(model_config)
autoencoder.compile(optimizer=optimizer,
                    loss='mae',
                    metrics=['mae'],
                    run_eagerly=False)

# ============ Test Model Summary ============ #
autoencoder.summary()

from callback import ProgbarLogger

progbar_callback = ProgbarLogger(count_mode='samples',
                                 stateful_metrics=['mae'])

print("\nEvaluation Before training - At Initialization")
autoencoder.evaluate(x=df_eval_conv,
Пример #13
0
    def _createMobilenetv2Backbone(self, output_stride=16):
        mobilenetv2 = MobileNetV2(weights='imagenet',
                                  input_shape=(self.dl_input_shape[1],
                                               self.dl_input_shape[2], 3),
                                  include_top=False)

        mobile_config = mobilenetv2.get_config()
        mobile_weights = mobilenetv2.get_weights()

        #tf.keras.backend.clear_session()

        assert output_stride in [
            8, 16
        ], "Only suported output_stride= 8 o 16 for backbone mobilenetv2."

        dilatation = 1
        for layer in mobile_config['layers']:
            if layer['name'] == 'input_1':
                layer['config']['batch_input_shape'] = (
                    None, self.dl_input_shape[-3], self.dl_input_shape[-2],
                    self.dl_input_shape[-1])
                self.logger.info(layer['name'] + ', ' +
                                 str(layer['config']['batch_input_shape']))

            if output_stride == 8:
                if layer['name'] == 'block_6_depthwise':
                    layer['config']['strides'] = (1, 1)
                    dilatation = dilatation * 2  #Replace stride for dilatation
                    self.logger.info(layer['name'] + ', strides=' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))
                if layer['name'] == 'block_7_depthwise':
                    layer['config']['dilation_rate'] = (dilatation, dilatation)
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))
                if layer['name'] == 'block_8_depthwise':
                    layer['config']['dilation_rate'] = (dilatation, dilatation)
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))
                if layer['name'] == 'block_9_depthwise':
                    layer['config']['dilation_rate'] = (dilatation, dilatation)
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))
                if layer['name'] == 'block_10_depthwise':
                    layer['config']['dilation_rate'] = (dilatation, dilatation)
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))
                if layer['name'] == 'block_11_depthwise':
                    layer['config']['dilation_rate'] = (dilatation, dilatation)
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))
                if layer['name'] == 'block_12_depthwise':
                    layer['config']['dilation_rate'] = (dilatation, dilatation)
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))
            if output_stride in [8, 16]:
                if layer['name'] == 'block_13_depthwise':
                    layer['config']['strides'] = (1, 1)
                    dilatation = dilatation * 2  #Replace stride for dilatation
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))
                if layer['name'] == 'block_14_depthwise':
                    layer['config']['dilation_rate'] = (dilatation, dilatation)
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))
                if layer['name'] == 'block_15_depthwise':
                    layer['config']['dilation_rate'] = (dilatation, dilatation)
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))
                if layer['name'] == 'block_16_depthwise':
                    layer['config']['dilation_rate'] = (dilatation, dilatation)
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))

#        tf.keras.backend.clear_session()
        new_mobilenetv2 = Model.from_config(mobile_config)
        mobile_weights[0] = np.resize(mobile_weights[0],
                                      [3, 3, self.dl_input_shape[-1], 32])
        new_mobilenetv2.set_weights(mobile_weights)

        self.backbone = Model(
            inputs=new_mobilenetv2.inputs,
            outputs=new_mobilenetv2.get_layer('block_16_project_BN').output)
        self.strideOutput32LayerName = 'block_16_project_BN'
        self.strideOutput16LayerName = 'block_12_add'
        self.strideOutput8LayerName = 'block_5_add'
        self.inputLayerName = mobilenetv2.layers[0].name
    def __build_sample_model(self, batch_input_length) -> dict:
        """
        Model that predicts a single OHE character.
        This model is generated from the modified config file of the self.batch_model.

        Returns:
            The dictionary of the configuration.
        """

        self.__batch_input_length = batch_input_length

        # Get the configuration of the batch_model
        config = self.model.get_config()

        # Keep only the "Decoder_Inputs" as single input to the sample_model
        config["input_layers"] = [config["input_layers"][0]]

        # Find decoder states that are used as inputs in batch_model and remove them
        idx_list = []
        for idx, layer in enumerate(config["layers"]):

            if "Decoder_State_" in layer["name"]:
                idx_list.append(idx)

        # Pop the layer from the layer list
        # Revert indices to avoid re-arranging after deleting elements
        for idx in sorted(idx_list, reverse=True):
            config["layers"].pop(idx)

        # Remove inbound_nodes dependencies of remaining layers on deleted ones
        for layer in config["layers"]:
            idx_list = []

            try:
                for idx, inbound_node in enumerate(layer["inbound_nodes"][0]):
                    if "Decoder_State_" in inbound_node[0]:
                        idx_list.append(idx)
            # Catch the exception for first layer (Decoder_Inputs) that has empty list of inbound_nodes[0]
            except:
                pass

            # Pop the inbound_nodes from the list
            # Revert indices to avoid re-arranging
            for idx in sorted(idx_list, reverse=True):
                layer["inbound_nodes"][0].pop(idx)

        # Change the batch_shape of input layer
        config["layers"][0]["config"]["batch_input_shape"] = (
            batch_input_length,
            1,
            self.dec_input_shape[-1],
        )

        # Finally, change the statefulness of the RNN layers
        for layer in config["layers"]:
            if "Decoder_LSTM_" in layer["name"]:
                layer["config"]["stateful"] = True
                # layer["config"]["return_sequences"] = True

        # Define the sample_model using the modified config file
        sample_model = Model.from_config(config)

        # Copy the trained weights from the trained batch_model to the untrained sample_model
        for layer in sample_model.layers:
            # Get weights from the batch_model
            weights = self.model.get_layer(layer.name).get_weights()
            # Set the weights to the sample_model
            sample_model.get_layer(layer.name).set_weights(weights)

        if batch_input_length == 1:
            self.__sample_model = sample_model

        elif batch_input_length > 1:
            self.__multi_sample_model = sample_model

        return config
Пример #15
0
    def _createVGG16Backbone(self, output_stride=16):
        vgg16 = VGG16(weights='imagenet',
                      input_shape=(self.dl_input_shape[1],
                                   self.dl_input_shape[2], 3),
                      include_top=False)

        assert output_stride in [
            8, 16
        ], "Only suported output_stride= 8 o 16 for backbone vgg16."

        mobile_config = vgg16.get_config()
        mobile_weights = vgg16.get_weights()
        #tf.keras.backend.clear_session()

        dilatation = 1
        stride_enable = False
        for layer in mobile_config['layers']:
            if layer['name'] == 'input_1':
                layer['config']['batch_input_shape'] = (
                    None, self.dl_input_shape[-3], self.dl_input_shape[-2],
                    self.dl_input_shape[-1])
                self.logger.info(layer['name'] + ', ' +
                                 str(layer['config']['batch_input_shape']))
            if output_stride == 8:
                if layer['name'] == 'block4_pool':
                    layer['config']['strides'] = (1, 1)
                    layer['config']['pool_size'] = (1, 1)
                    dilatation = dilatation * 2  #Replace stride for dilatation
                    self.logger.info(layer['name'] + ', strides=' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['pool_size']))
                    stride_enable = True

            if output_stride in [8, 16]:
                if layer['name'] == 'block5_pool':
                    layer['config']['strides'] = (1, 1)
                    layer['config']['pool_size'] = (1, 1)
                    dilatation = dilatation * 2  #Replace stride for dilatation
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['pool_size']))
                    stride_enable = True
                if 'conv' in layer['name'] and stride_enable:
                    layer['config']['dilation_rate'] = (dilatation, dilatation)
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))

        new_vgg16 = Model.from_config(mobile_config)
        mobile_weights[0] = np.resize(mobile_weights[0], [
            mobile_weights[0].shape[0], mobile_weights[0].shape[1],
            self.dl_input_shape[-1], mobile_weights[0].shape[-1]
        ])  #update input to suport 4 channels
        new_vgg16.set_weights(mobile_weights)

        x = new_vgg16.output
        x = Conv2D(filters=512,
                   kernel_size=3,
                   name='block_6_conv1',
                   padding="same",
                   dilation_rate=dilatation,
                   activation='relu')(x)
        x = Conv2D(filters=512,
                   kernel_size=3,
                   name='block_6_conv2',
                   padding="same",
                   dilation_rate=dilatation,
                   activation='relu')(x)
        x = Conv2D(filters=512,
                   kernel_size=3,
                   name='block_6_conv3',
                   padding="same",
                   dilation_rate=dilatation,
                   activation='relu')(x)

        self.backbone = Model(inputs=new_vgg16.inputs, outputs=x)
        self.strideOutput32LayerName = 'block6_conv3'
        self.strideOutput16LayerName = 'block5_conv3'
        self.strideOutput8LayerName = 'block4_conv3'
        self.inputLayerName = vgg16.layers[0].name
Пример #16
0
def convert(prevmodel, export_path, export_name):

    graph1 = tf.Graph()
    with graph1.as_default():
        sess1 = tf.Session()
        with sess1.as_default():
            previous_model = load_model(prevmodel)
            previous_model.summary()
            config = previous_model.get_config()
            weights = previous_model.get_weights()

    graph2 = tf.Graph()
    with graph2.as_default():
        sess2 = tf.Session()
        with sess2.as_default():
            K.set_learning_phase(0)
            try:
                model = Sequential.from_config(config)
            except:
                model = Model.from_config(config)
            model.set_weights(weights)

            with open(
                    os.path.join(export_path,
                                 export_name + '.input_output.txt'),
                    'w') as fid:
                model_input_name = model.input.name
                #model_input_node_name
                model_output_name = model.output.name
                print(f"Input name: {model_input_name}")
                print(f"Output name: {model_output_name}")
                fid.write(f"{model_input_name}\n")
                fid.write(f"{model_output_name}\n")

            model_output_node_name = model.output.name.split(':')[0]

            graph_file = os.path.join(export_path,
                                      export_name + ".graph.pbtxt")
            ckpt_file = os.path.join(export_path, export_name + ".ckpt")
            saver = tf.train.Saver()
            tf.train.write_graph(sess2.graph_def, '', graph_file)
            save_path = saver.save(sess2, ckpt_file)

            # freeze the graph
            frozen_graph_def = tf.graph_util.convert_variables_to_constants(
                sess2,  # The session is used to retrieve the weights
                graph2.as_graph_def(
                ),  # The graph_def is used to retrieve the nodes
                model_output_node_name.split(
                    ","
                )  # The output node names are used to select the usefull nodes
            )

            # Finally we serialize and dump the output graph to the filesystem
            frozen_graph_path = os.path.join(export_path,
                                             export_name + ".frozen.pb")
            with tf.gfile.GFile(frozen_graph_path, "wb") as f:
                f.write(frozen_graph_def.SerializeToString())

    #tf.reset_default_graph()
    #frozen_graph_def = freeze_graph(export_path, model_output_node_name)

    tf.reset_default_graph()
    train_writer = tf.summary.FileWriter(export_path)
    train_writer.add_graph(frozen_graph_def)
    train_writer.flush()

    # optimize for inference
    optimized_graph_def = optimize_for_inference_lib.optimize_for_inference(
        frozen_graph_def, [model_input_name.split(':')[0]],
        [model_output_name.split(':')[0]], tf.float32.as_datatype_enum)
    #tf.int32.as_datatype_enum

    optimized_graph_path = os.path.join(
        export_path, export_name + ".optimized_for_inference.pb")
    with tf.gfile.GFile(optimized_graph_path, "wb") as f:
        f.write(optimized_graph_def.SerializeToString())

        # tflite
        # ## from frozen graph
        converter = tflite.TocoConverter.from_frozen_graph(
            optimized_graph_path, [model_input_name.split(':')[0]],
            [model_output_name.split(':')[0]],
            {model_input_name.split(':')[0]: [1, 32, 32, 3]})
    #
    ## from keras model file
    # only available in tensorflow >=1.11
    #converter = tflite.TocoConverter.from_keras_model_file(prevmodel)
    converter.post_training_quantize = True
    #converter.inference_type = tf.quint8
    #converter.inference_input_type = tf.float32
    tflite_quantized_model = converter.convert()
    optimized_graph_path = os.path.join(export_path, export_name + ".tflite")
    open(optimized_graph_path, "wb").write(tflite_quantized_model)
Пример #17
0
    def _createResnetBackbone(self, output_stride=16, depth='101'):
        resnet101 = ResNet101(weights='imagenet',
                              input_shape=(self.dl_input_shape[1],
                                           self.dl_input_shape[2], 3),
                              include_top=False)

        assert output_stride in [
            8, 16
        ], "Only suported output_stride= 8 o 16 for backbone resnet."

        resnet101_config = resnet101.get_config()
        resnet101_weights = resnet101.get_weights()
        #tf.keras.backend.clear_session()

        output_stride = 8
        dilatation = 1
        stride_enable = False
        for layer in resnet101_config['layers']:
            if layer['name'] == 'input_1':
                layer['config']['batch_input_shape'] = (
                    None, self.dl_input_shape[-3], self.dl_input_shape[-2],
                    self.dl_input_shape[-1])
                self.logger.info(layer['name'] + ', ' +
                                 str(layer['config']['batch_input_shape']))
            if output_stride == 8 and (layer['name'] == 'conv4_block1_1_conv'
                                       or layer['name']
                                       == 'conv4_block1_0_conv'):
                layer['config']['strides'] = (1, 1)
                self.logger.info(layer['name'] + ', strides=' +
                                 str(layer['config']['strides']) + ', ' +
                                 str(layer['config']['dilation_rate']))
                stride_enable = True
                if layer['name'] == 'conv4_block1_1_conv':
                    dilatation = dilatation * 2  #Replace stride for dilatation

            elif output_stride in [8, 16]:
                if layer['name'] == 'conv5_block1_1_conv' or layer[
                        'name'] == 'conv5_block1_0_conv':
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))
                    layer['config']['strides'] = (1, 1)
                    self.logger.info(layer['name'] + ', ' +
                                     str(layer['config']['strides']) + ', ' +
                                     str(layer['config']['dilation_rate']))
                    stride_enable = True
                    if layer['name'] == 'conv5_block1_1_conv':
                        dilatation = dilatation * 2  #Replace stride for dilatation
                elif stride_enable and ('_conv' in layer['name']):
                    if layer['config']['kernel_size'] != (1, 1):
                        layer['config']['dilation_rate'] = (dilatation,
                                                            dilatation)
                        self.logger.info(layer['name'] + ', ' +
                                         str(layer['config']['strides']) +
                                         ', ' +
                                         str(layer['config']['dilation_rate']))
                    else:
                        self.logger.info(layer['name'] + ', ' +
                                         str(layer['config']['strides']) +
                                         ', ' +
                                         str(layer['config']['dilation_rate']))

        self.backbone = Model.from_config(resnet101_config)
        resnet101_weights[0] = np.resize(resnet101_weights[0], [
            resnet101_weights[0].shape[0], resnet101_weights[0].shape[1],
            self.dl_input_shape[-1], resnet101_weights[0].shape[-1]
        ])  #update input to suport 4 channels
        self.backbone.set_weights(resnet101_weights)

        self.strideOutput32LayerName = 'conv5_block3_out'
        self.strideOutput16LayerName = 'conv4_block23_out'
        self.strideOutput8LayerName = 'conv3_block4_out'
        self.inputLayerName = resnet101.layers[0].name
Пример #18
0
def partial_trainability(model_keras, Layer_names, Layer_trainabliities):
    """
    This function allows you to get partially trainable layers
    function takes
    model_keras: keras model you have loaded or created for example using model_zoo.get_model("VGG_small_4",32,3,2)
    Layer_names: list containing the names of the layers that should be changed. Of course these names have to be existing in model_keras
    Layer_trainability: list containing floats. For each layer that should be changed, provide a value between 0 and 1 (0-layer not trainable at all; 1-layer entirely trainable)
    
    Lets say you use Layer_names=['dense_3'] and Layer_trainability=[0.25]
    Lets assume 'dense_3' has 1000 nodes.
    Then two new parallell dense layers will be created. 
    The first one gets 750 nodes, which are set to set to Trainable=False.
    The second dense layer has 250 nodes, which are trainable.
    The corresponding weights from the initial model are distributed to these 
    layer accordingly.    
    """
    #Get the config of the current model
    model_config = model_keras.get_config()
    #Deep-Copy the config of the  original model
    model_config_new = copy.deepcopy(model_config)

    if type(model_config_new) == dict:
        print("Model used functional API of Keras")
    elif type(model_config_new) == list:
        print(
            "Model used sequential API of Keras and will now be converted to functional API"
        )
        #api = "Sequential"
        #Convert to functional API
        input_layer = Input(batch_shape=model_keras.layers[0].input_shape)
        prev_layer = input_layer
        for layer in model_keras.layers:
            prev_layer = layer(prev_layer)
        model_keras = Model([input_layer], [prev_layer])
        #Now we have functional API :)
        #Get the model config for the converted model
        model_config = model_keras.get_config()
        model_config_new = copy.deepcopy(model_config)
    else:
        print("Unknown format for model config")
        #return

    Layer_nontrainability = list(1 - np.array(Layer_trainabliities))
    del Layer_trainabliities
    #Original names of the layers
    Layer_names_orig = [
        model_keras.layers[i].name for i in range(len(model_keras.layers))
    ]
    #Now we are starting to loop over all the requested changes:
    for i in range(len(Layer_names)):
        nontrainability = Layer_nontrainability[i]
        layer_name = Layer_names[i]
        layer_names_list = [
            model_config_new["layers"][it]['name']
            for it in range(len(model_config_new["layers"]))
        ]
        layer_index = int(
            np.where(np.array(layer_names_list) == layer_name)[0])
        layer_config = model_config_new['layers'][layer_index]
        layer_type = layer_config["class_name"]
        if layer_type == "Dense":
            split_property = "units"  #'units' are the number of nodes in dense layers
        elif layer_type == "Conv2D":
            split_property = "filters"

        nr_nodes = layer_config["config"][split_property]
        nr_const = int(np.round(nontrainability * nr_nodes))
        #get a config for the non-trainable part

        layer_config_const = copy.deepcopy(layer_config)
        layer_name_const = layer_config_const['config']["name"] + "_1"
        layer_config_const["config"][split_property] = nr_const
        layer_config_const["config"]["trainable"] = False  #not trainable
        layer_config_const["config"]["name"] = layer_name_const  #rename
        layer_config_const["name"] = layer_name_const  #rename

        #get a config for the rest (trainable part)
        layer_config_rest = copy.deepcopy(layer_config)
        #this part will only exist if nr_nodes-nr_const>0:
        if nr_nodes - nr_const > 0:
            layer_name_rest = layer_config_rest["config"]["name"] + "_2"
            layer_config_rest["config"][split_property] = nr_nodes - nr_const
            layer_config_rest["config"]["name"] = layer_name_rest  #rename
            layer_config_rest["name"] = layer_name_rest  #rename

        #Assemble a config for a corresponding concatenate layer
        inbound_1 = [layer_name_const, 0, 0, {}]
        inbound_2 = [layer_name_rest, 0, 0, {}]
        inbound_nodes = [inbound_1, inbound_2]
        layer_name = layer_config['config'][
            "name"]  #Call it like the initial layer that has been there. This will allow other layers to correctly conncet like before #'concatenate_'+layer_config["config"]["name"]
        config_conc = {"axis": -1, "name": layer_name, "trainable": True}
        conc_dict = {
            "class_name": 'Concatenate',
            "config": config_conc,
            "inbound_nodes": [inbound_nodes],
            "name": layer_name
        }

        #insert these layers into the config at Index: layer_index
        layerlist = model_config_new["layers"]
        #Replace existing layer with the const part
        layerlist[layer_index] = layer_config_const
        #After that insert the rest part
        layerlist.insert(layer_index + 1, layer_config_rest)
        #After that insert the concatenate layer
        layerlist.insert(layer_index + 2, conc_dict)
        #Update the config with the new layers
        model_config_new["layers"] = layerlist

    #Build the model using this updated config
    model_keras_new = Model.from_config(model_config_new)
    #Compilation might not be required.
    model_keras_new.compile(loss='categorical_crossentropy',
                            optimizer='adam',
                            metrics=['accuracy'])

    iterator = 0
    for layer_name in Layer_names_orig:  #for all layers of the original model
        layer = model_keras.get_layer(layer_name)
        if layer_name not in Layer_names:  #if this layer was not subjected to change in the new model...
            #Straight forward: get weights of the orignal model
            weights = layer.get_weights()
            #And put them into the new model
            model_keras_new.get_layer(layer_name).set_weights(weights)
        else:  #Otherwise the layer was changed
            layer_type = layer.__class__.__name__
            layer_config = layer.get_config()
            weights = layer.get_weights()  #Get the original weights
            trainability = Layer_nontrainability[iterator]
            iterator += 1

            if layer_type == "Dense":
                split_property = "units"  #'units' are the number of nodes in dense layers
            elif layer_type == "Conv2D":
                split_property = "filters"

            nr_nodes = layer_config[split_property]
            nr_const = int(np.round(trainability * nr_nodes))

            #Constant part
            if layer_type == "Dense":
                #Put the former weights into the layer
                weights_const = list(np.copy(weights))
                weights_const[0] = weights_const[0][:, 0:nr_const]
                weights_const[1] = weights_const[1][0:nr_const]
            elif layer_type == "Conv2D":
                #Put the former weights into the layer
                weights_const = list(np.copy(weights))
                weights_const[0] = weights_const[0][:, :, :, 0:nr_const]
                weights_const[1] = weights_const[1][0:nr_const]
            else:
                print("Unknown layer type")
                #return
            layer_name_const = layer_name + "_1"  #rename
            model_keras_new.get_layer(layer_name_const).set_weights(
                weights_const)

            #Rest trainable part
            #this part will only exist if nr_nodes-nr_const>0:
            if nr_nodes - nr_const > 0:
                if layer_type == "Dense":
                    #Get the weights
                    weights_rest = list(np.copy(weights))
                    weights_rest[0] = weights_rest[0][:, nr_const:]
                    weights_rest[1] = weights_rest[1][nr_const:]
                if layer_type == "Conv2D":
                    #Get the weights
                    weights_rest = list(np.copy(weights))
                    weights_rest[0] = weights_rest[0][:, :, :, nr_const:]
                    weights_rest[1] = weights_rest[1][nr_const:]

                layer_name_rest = layer_name + "_2"  #rename
                model_keras_new.get_layer(layer_name_rest).set_weights(
                    weights_rest)
    return model_keras_new
Пример #19
0
def build_pruned_model(model, new_model_param, layer_types, num_new_neurons,
                       num_new_filters, comp):
    """
    The new number of neurons and filters are changed in the model config.
    Load the new weight matrices into the model.
    
    Args: 
        model: Model which should be pruned
        new_model_param: Stores the new weights of the model
        layer_types: The types of all layers of the model
        num_new_neurons: Number of neurons of the dense layers
        num_new_filters: Number of filters of the conv layers
        
    Return: 
        pruned_model: New model after pruning all dense and conv layers
    """

    model_config = model.get_config()
    '''
    For functional model first layer is the input layer.
    For sequential model the first layer is the layer after the input layer
    '''
    a = 1
    if layer_types[0] == 'InputLayer':
        a = 0

    for i in range(0, len(model_config['layers']) - 3):
        if model_config['layers'][i + a][
                'class_name'] == "Dense":  #i+1 because first layer of model is the inputlayer
            print("Dense")
            model_config['layers'][i +
                                   a]['config']['units'] = num_new_neurons[i]

        elif model_config['layers'][i + a]['class_name'] == "Conv2D":
            print("Conv2D")
            model_config['layers'][i +
                                   a]['config']['filters'] = num_new_filters[i]

        elif model_config['layers'][i + a]['class_name'] == "Reshape":
            temp_list = list(
                model_config['layers'][i + a]['config']['target_shape'])
            cur_layer = i
            cur_filters = num_new_filters[cur_layer]
            #Get number of filters of last Conv layer
            if cur_filters == 0:
                while cur_filters == 0:
                    cur_layer -= 1
                    cur_filters = num_new_filters[cur_layer]
            temp_list[2] = cur_filters
            temp_tuple = tuple(temp_list)
            model_config['layers'][i +
                                   a]['config']['target_shape'] = temp_tuple

        else:
            print("No Dense or Conv2D")

    print("Before pruning:")
    model.summary()

    if "Sequential" in str(model):
        pruned_model = Sequential.from_config(model_config)
    elif "Functional" in str(model):
        pruned_model = Model.from_config(model_config)

    print("After pruning:")
    pruned_model.summary()

    for i in range(0, len(pruned_model.layers)):
        if len(new_model_param[i]) != 0:
            pruned_model.layers[i].set_weights(new_model_param[i])
        else:
            None

    pruned_model.compile(**comp)

    return pruned_model