Esempio n. 1
0
    def __init__(self):
        print("Prepare conversion form Keras model to Graph model")
        self.__delete_tmp_directory()
        if not os.path.exists(self.base_dir):
            print("make directory: '{:s}'".format(self.base_dir))
            os.makedirs(self.base_dir)
        if not os.path.exists(self.tf_model_dir):
            print("make directory: '{:s}'".format(self.tf_model_dir))
            os.makedirs(self.tf_model_dir)
        if not os.path.exists(self.graph_dir):
            print("make directory: '{:s}'".format(self.graph_dir))
            os.makedirs(self.graph_dir)

        self.output_layer_name = ""
        self.input_layer_name = ""
        self.wait = Spinner()
        self.lock = threading.Lock()
Esempio n. 2
0
 def __init__(self,
              epochs,
              batch_size,
              learning_rate=0.0001,
              image_width=224,
              image_height=224):
     self.m_epochs = epochs
     self.m_batch_size = batch_size
     self.m_lr = learning_rate
     self.m_image_width = image_width
     self.m_image_height = image_height
     self.__pathdir = 'Model'
     self.__spin = Spinner()
     # export config data in dict
     self.m_config["epochs"] = self.m_epochs
     self.m_config["batch_size"] = self.m_batch_size
     self.m_config["learning_rate"] = self.m_lr
     self.m_config["image_width"] = self.m_image_width
     self.m_config["image_height"] = self.m_image_height
Esempio n. 3
0
class KerasToNCSGraph(object):
    model_ = None  # store model
    tf_model_ = None  # tensorflow meta file graph structure
    base_dir = os.getcwd() + '/ModelGraph'
    tf_model_dir = base_dir + '/tf_model/'  # folder tensorflow model
    graph_dir = base_dir + '/graph_model/'  # folder graph model

    def __init__(self):
        print("Prepare conversion form Keras model to Graph model")
        self.__delete_tmp_directory()
        if not os.path.exists(self.base_dir):
            print("make directory: '{:s}'".format(self.base_dir))
            os.makedirs(self.base_dir)
        if not os.path.exists(self.tf_model_dir):
            print("make directory: '{:s}'".format(self.tf_model_dir))
            os.makedirs(self.tf_model_dir)
        if not os.path.exists(self.graph_dir):
            print("make directory: '{:s}'".format(self.graph_dir))
            os.makedirs(self.graph_dir)

        self.output_layer_name = ""
        self.input_layer_name = ""
        self.wait = Spinner()
        self.lock = threading.Lock()

    @staticmethod
    def freeze_session(session,
                       keep_var_names=None,
                       output_names=None,
                       clear_devices=True):
        """
        Freezes the state of a session into a pruned computation graph.

        Creates a new computation graph where variable nodes are replaced by
        constants taking their current value in the session. The new graph will be
        pruned so subgraphs that are not necessary to compute the requested
        outputs are removed.
        :param: session The TensorFlow session to be frozen.
        :param: keep_var_names A list of variable names that should not be frozen,
                              or None to freeze all the variables in the graph.
        :param: output_names Names of the relevant graph outputs.
        :param: clear_devices Remove the device directives from the graph for better portability.
        :return: The frozen graph definition.
        """
        from tensorflow.python.framework.graph_util import convert_variables_to_constants
        graph = session.graph
        with graph.as_default():
            freeze_var_names = list(
                set(v.op.name
                    for v in tf.global_variables()).difference(keep_var_names
                                                               or []))
            output_names = output_names or []
            output_names += [v.op.name for v in tf.global_variables()]
            input_graph_def = graph.as_graph_def()
            if clear_devices:
                for node in input_graph_def.node:
                    node.device = ""
            frozen_graph = convert_variables_to_constants(
                session, input_graph_def, output_names, freeze_var_names)
            return frozen_graph

    def set_keras_model_file(self,
                             model_file='',
                             weights_file=None,
                             view_summary=False):
        """
        Import trained model files.
        :param model_file (str) path to file model import 'json' or model ('.model', '.h5')
        :param weights_file (str) path to file h5 import weights model
        :param view_summary (bool) print on screen the model's summary
        """

        if os.path.exists(model_file) and weights_file is None:
            self.wait.start()
            self.lock.acquire()
            try:
                if model_file.endswith((".h5", ".model")):
                    self.model_ = load_model(model_file)
            except IOError as err:
                print("Could not read file:", model_file)
                sys.exit(err)
            self.lock.release()
            self.wait.stop()
            print("Done")
        elif os.path.exists(model_file) and weights_file is not None:
            self.wait.start()
            self.lock.acquire()
            try:
                if os.path.exists(model_file) and model_file.endswith(".json"):
                    with open(model_file, 'r') as model_input:
                        model = model_input.read()
                        self.model_ = model_from_json(model)
            except IOError as err:
                print("Could not read file: ", model_file)
                sys.exit(err)
            try:
                if os.path.exists(weights_file) and weights_file.endswith(
                        ".h5"):
                    self.model_.load_weights(weights_file)  # load weights
            except IOError as err:
                print("Could not read file: ", weights_file)
                sys.exit(err)
            self.lock.release()
            self.wait.stop()
            print("Done")
            return
        else:
            print("No files found")
            sys.exit(0)

        if view_summary:
            print('Model Summary:',
                  self.model_.summary())  # print summary model

    def convertGraph(self, name="model"):
        """
        Converts an HD5F file to a .pb file for use with Tensorflow.
        :param  numoutputs (int)
        :param  prefix (str) the prefix of the output aliasing
        :param  name (str) the name of ProtocolBuffer file
        """
        print("Start conversion in Protocol Buffer")
        frozen_graph = self.freeze_session(
            kbe.get_session(),
            output_names=[out.op.name for out in self.model_.outputs])

        f = '{}.pb'.format(name)
        tf.train.write_graph(frozen_graph, self.tf_model_dir, f, as_text=False)
        print('Saved the graph definition at: ', self.tf_model_dir, f)

        # Write the graph in human readable
        f = '{}.pb.ascii'.format(name)
        tf.train.write_graph(sess.graph.as_graph_def(),
                             self.tf_model_dir,
                             f,
                             as_text=True)
        print('Saved the graph definition in ascii format at: ',
              self.tf_model_dir, f)
        # save last layer for output nodes
        self.output_layer_name = "".join(self.get_names())
        print("Output layer node: ", self.output_layer_name)
        self.tf_model_ = os.path.join(self.tf_model_dir, name + ".pb")
        # compile
        self.__compile_graph_model(name_graph_model_file=name)

    def get_names(self):
        return [out.op.name for out in self.model_.outputs]

    def __compile_graph_model(self, name_graph_model_file='model'):
        """
        Compile graph model for Neural Compute Stick (Intel Movidius) starting from Tensorflow model.
        :param name_graph_model_file (str) assign name of model exported
        """
        graph_model = self.graph_dir
        graph_model += name_graph_model_file + '.graph'  # complete graph file model (path + name)
        # assemble command
        cmd = 'mvNCCompile {0} -s 12 -in {1} -on {2} -o {3}'.format(
            self.tf_model_, 'input_1', self.output_layer_name, graph_model)
        print(
            "==> copy and paste command below to create a graph model for Intel Movidius:"
        )
        print(cmd)
        # start compile

    def __delete_tmp_directory(self):
        if os.path.exists(self.base_dir):
            print("removing previous temporary files")
            shutil.rmtree(self.base_dir, ignore_errors=True)

    @staticmethod
    def title():
        print(
            "     )                                                           "
        )
        print(
            "  ( /(                    )                                    ) "
        )
        print(
            "  )\()) (  (      )    ( /(             (  ( (      )       ( /( "
        )
        print(
            "|((_)\ ))\ )(  ( /( (  )(_))(     (  (  )\))()(  ( /( `  )  )\())"
        )
        print(
            "|_ ((_)((_|()\ )(_)))\((_)  )\ )  )\ )\((_))(()\ )(_))/(/( ((_)\ "
        )
        print(
            "| |/ (_))  ((_|(_)_((_)_  )_(_/( ((_|(_)(()(_|(_|(_)_((_)_\| |(_)"
        )
        print(
            "| ' </ -_)| '_/ _` (_-</ /| ' \)) _|(_-< _` | '_/ _` | '_ \) ' \ "
        )
        print(
            "|_|\_\___||_| \__,_/__/___|_||_|\__|/__|__, |_| \__,_| .__/|_||_|"
        )
        print(
            "                                     |___/         |_|         \n"
        )

    def __del__(self):
        del self.model_
        del self.tf_model_
Esempio n. 4
0
class FaceRecognition(ConvolutionNeuralNetwork):
    m_train_generator = None
    m_valid_generator = None
    m_model = None
    m_num_train_samples = 0
    m_num_classes = 0
    m_num_validate_samples = 0
    m_config = {}

    def __init__(self,
                 epochs,
                 batch_size,
                 learning_rate=0.0001,
                 image_width=224,
                 image_height=224):
        self.m_epochs = epochs
        self.m_batch_size = batch_size
        self.m_lr = learning_rate
        self.m_image_width = image_width
        self.m_image_height = image_height
        self.__pathdir = 'Model'
        self.__spin = Spinner()
        # export config data in dict
        self.m_config["epochs"] = self.m_epochs
        self.m_config["batch_size"] = self.m_batch_size
        self.m_config["learning_rate"] = self.m_lr
        self.m_config["image_width"] = self.m_image_width
        self.m_config["image_height"] = self.m_image_height

    def set_train_generator(self, train_dir):
        """
        Connect the image generator to a folder contains the source images the image generator alters.
        :param train_dir: (str) containing the path to the folder
        """
        #   Training image generator
        self.m_num_train_samples = self.get_num_files(train_dir)
        self.m_num_classes = self.get_num_subfolders(train_dir)
        train_generator = self.create_img_generator()
        self.m_train_generator = train_generator.flow_from_directory(
            directory=train_dir,
            target_size=(self.m_image_width, self.m_image_height),
            batch_size=self.m_batch_size,
            seed=42  # set seed for reproducibility
        )
        label_map = self.m_train_generator.class_indices
        label_map_ = dict((v, k) for k, v in label_map.items())  # flip k,v
        self.m_config["label_map"] = label_map_

    def set_valid_generator(self, valid_dir):
        """
        Connect the image generator to a folder contains the source images the image generator alters.
        :param valid_dir: (str) containing the path folder
        """
        self.m_num_validate_samples = self.get_num_files(valid_dir)
        valid_generator = self.create_img_generator()
        self.m_valid_generator = valid_generator.flow_from_directory(
            directory=valid_dir,
            target_size=(self.m_image_width, self.m_image_height),
            batch_size=self.m_batch_size,
            seed=42  # set seed for reproducibility
        )

    def train_and_fit_model(self, figure_history_name):
        """Train the model"""
        history = self.m_model.fit_generator(
            self.m_train_generator,
            epochs=self.m_epochs,
            steps_per_epoch=self.m_num_train_samples // self.m_batch_size,
            validation_data=self.m_valid_generator,
            validation_steps=self.m_num_validate_samples // self.m_batch_size,
            class_weight='auto',
            use_multiprocessing=True)
        # print plot training (accuracy vs lost)
        plotter = HistoryAnalysis.plot_history(history, figure_history_name)

    def load_model_from_file(self, filename, weights_file=None):
        """
        Import trained model store as 1 file ('.model', '.h5')
        Or import the schema model in format 'json' and weights's file in format h5.
        :param filename: (str) pass path model file
        :param weights_file: (str) pass path weights file
        """
        if os.path.exists(filename) and weights_file is None:
            print("Loading model, please wait")
            self.__spin.start()
            # load entire model
            if filename.endswith(('.model', '.h5')):
                self.m_model = load_model(filename)
                self.__spin.stop()
                print("Done")
            else:
                self.__spin.stop()
                raise ValueError(
                    "Invalid extension, supported extensions are: '.h5', '.model'"
                )

        elif os.path.exists(filename) and weights_file is not None:
            if filename.endswith('.json') and weights_file.endswith('.h5'):
                print("Loading model, please wait")
                self.__spin.start()
                # Model reconstruction from JSON file
                with open(filename, 'r') as f:
                    self.m_model = model_from_json(f.read())
                # Load weights into the new model
                self.m_model.load_weights(weights_file)
                self.__spin.stop()
                print("Done")
            else:
                self.__spin.stop()
                raise FileNotFoundError(errno.ENOENT,
                                        os.strerror(errno.ENOENT),
                                        (filename, weights_file))

        else:
            raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT),
                                    filename)

        print(self.m_model.summary())

    def save_model_to_file(self,
                           name='model',
                           extension='.h5',
                           export_image=False):
        """
        Export trained model store as 1 file ('.model', '.h5')
        or export the schema model in format 'json' and weights's file in format h5.
        :param name: (str) assign file name
        :param extension: (str) assign file extension
        :param export_image: (bool) generate figure schema model
        """
        print("Saving model, please wait")
        # self.__spin.start()
        root_dir = os.getcwd()
        print("work directory: ", root_dir)
        dest_dir = os.path.join(root_dir, 'Model')
        print('destination directory:', dest_dir)
        if not os.path.exists(dest_dir):
            os.makedirs(dest_dir)
        # build the name-file
        filename = os.path.join(dest_dir, (name + extension))
        if extension not in ['.h5', '.model', '.json']:
            self.__spin.stop()
            raise ValueError(
                "Invalid extension, supported extensions are: '.h5', '.model', '.json'"
            )
        if extension == '.h5':
            # export complete model with weights
            self.m_model.save(filename)
            print('Saved model at: ', dest_dir, filename)
        elif extension == '.model':
            # export complete model with weights
            self.m_model.save(filename)
            print('Saved model at: ', dest_dir, filename)
        elif extension == '.json':
            # save as JSON and weights
            model_json = self.m_model.to_json()
            with open(filename, "w") as json_file:
                json_file.write(model_json)
                print('Saved model definition at: ', dest_dir, filename)
            # save weights
            namefile_weights = os.path.join(dest_dir, (name + '_weights.h5'))
            print(namefile_weights)
            self.m_model.save_weights(namefile_weights)
            print('Saved model weights at: ', dest_dir, filename)

        if export_image:
            image_name = os.path.join(dest_dir, (name + '.png'))
            # print image of schema model
            plot_model(self.m_model,
                       to_file=image_name,
                       show_layer_names=True,
                       show_shapes=True)

        # export as tensorflow .pb
        # especially when run on Altair PBS system keras return 0 size file
        frozen_graph = self.freeze_session(
            kbe.get_session(),
            output_names=[out.op.name for out in self.m_model.outputs])

        f = '{:s}.pb'.format(name)
        tf.train.write_graph(frozen_graph, dest_dir, f, as_text=False)
        print('Saved the graph definition at: ', dest_dir, f)

        # Write the graph in human readable
        f = '{:s}.pb.ascii'.format(name)
        tf.train.write_graph(sess.graph.as_graph_def(),
                             dest_dir,
                             f,
                             as_text=True)
        print('Saved the graph definition in ascii format at: ', dest_dir, f)

        # self.__spin.stop()
        self.__export_configuration(dest_dir, name)
        print("Done")

    def get_pretrained_model(self,
                             pretrained_model,
                             weights='imagenet',
                             include_top=False):
        """
        This method allows to define already existing neural networks and to export their model as a starting point.
        :param pretrained_model: (string) set name of neural network as inception, vgg16 ecc.
        :param weights: (string) set weights of NN
        :param include_top: (bool)
        :return model_base: (obj) the model select
        :return output: (obj) pre-trained NN weights
        """
        model_base = None
        output = None
        if pretrained_model == 'inception':
            model_base = InceptionV3(
                include_top=include_top,
                weights=weights,
                input_shape=self.m_train_generator.image_shape)
            output = model_base.output

        elif pretrained_model == 'xception':
            model_base = Xception(
                include_top=include_top,
                weights=weights,
                input_shape=self.m_train_generator.image_shape)
            output = (Flatten())(model_base.output)

        elif pretrained_model == 'resnet50':
            model_base = ResNet50(
                include_top=include_top,
                weights=weights,
                input_shape=self.m_train_generator.image_shape)
            output = model_base.output

        elif pretrained_model == 'vgg16':
            model_base = VGG16(include_top=include_top,
                               weights=weights,
                               input_shape=self.m_train_generator.image_shape)
            output = model_base.output

        elif pretrained_model == 'vgg19':
            model_base = VGG19(include_top=include_top,
                               weights=weights,
                               input_shape=self.m_train_generator.image_shape)
            output = model_base.output

        return model_base, output

    def set_face_recognition_model(self,
                                   pretrained_model='',
                                   weights='',
                                   include_top=False,
                                   Number_FC_Neurons=1024,
                                   trainable_parameters=False,
                                   num_trainable_parameters=1.0):
        """
        It allows to use different neural networks of convulsion, the first is based on the face recognition model
        VGG16 Oxford University, available at the address '' and personalized.
        Instead, those defined succinctly are the expansion of existing networks with the addition of the custom
        classifier. Furthermore, it is possible to specify whether to train all parameters or just some parameters,
        simply setting a dimensionless range between 0 and 1.0.
        :param pretrained_model:
        :param weights:
        :param include_top:
        :param Number_FC_Neurons:
        :param trainable_parameters:
        :param num_trainable_parameters:
        :return self(object):
        """
        if pretrained_model == '':  # use own custom model
            try:  # check minimum size image
                # define input model block
                x_input = Input(self.m_train_generator.image_shape)
                model_base = x_input
                x = (ZeroPadding2D((1, 1), name="InputLayer"))(x_input)
                # block 1
                x = (Convolution2D(64, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block1_conv1"))(x)
                x = (ZeroPadding2D((1, 1)))(x)
                x = (Convolution2D(64, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block1_conv2"))(x)
                x = (MaxPooling2D((2, 2),
                                  data_format="channels_first",
                                  strides=(2, 2)))(x)
                # block 2
                x = (ZeroPadding2D((1, 1)))(x)
                x = (Convolution2D(128, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block2_conv1"))(x)
                x = (ZeroPadding2D((1, 1)))(x)
                x = (Convolution2D(128, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block2_conv2"))(x)
                x = (MaxPooling2D((2, 2),
                                  data_format="channels_first",
                                  strides=(2, 2)))(x)
                # block 3
                x = (ZeroPadding2D((1, 1)))(x)
                x = (Convolution2D(256, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block3_conv1x"))(x)
                x = (ZeroPadding2D((1, 1)))(x)
                x = (Convolution2D(256, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block3_conv2"))(x)
                x = (ZeroPadding2D((1, 1)))(x)
                x = (Convolution2D(256, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block3_conv3"))(x)
                x = (MaxPooling2D((2, 2),
                                  data_format="channels_first",
                                  strides=(2, 2)))(x)
                # block 4
                x = (ZeroPadding2D((1, 1)))(x)
                x = (Convolution2D(512, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block4_conv1"))(x)
                x = (ZeroPadding2D((1, 1)))(x)
                x = (Convolution2D(512, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block4_conv2"))(x)
                x = (ZeroPadding2D((1, 1)))(x)
                x = (Convolution2D(512, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block4_conv3"))(x)
                x = (MaxPooling2D((2, 2),
                                  data_format="channels_first",
                                  strides=(2, 2)))(x)
                # block 5
                x = (ZeroPadding2D((1, 1)))(x)
                x = (Convolution2D(512, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block5_conv1"))(x)
                x = (ZeroPadding2D((1, 1)))(x)
                x = (Convolution2D(512, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block5_conv2"))(x)
                x = (ZeroPadding2D((1, 1)))(x)
                x = (Convolution2D(512, (3, 3),
                                   activation='relu',
                                   padding="same",
                                   name="block5_conv3"))(x)
                x = (MaxPooling2D((2, 2),
                                  data_format="channels_first",
                                  strides=(2, 2)))(x)
                # classification block
                x = (Convolution2D(4096, (7, 7),
                                   activation='relu',
                                   padding="same",
                                   name="fc1"))(x)
                x = (Dropout(0.5))(x)
                x = (Convolution2D(4096, (1, 1), activation='relu',
                                   name="fc2"))(x)
                x = (Dropout(0.5))(x)
                x = (Convolution2D(2048, (1, 1)))(x)
                # Classification block
                x = Flatten()(x)
                x = Activation(activation='softmax')(x)

            except ValueError as err:
                message = "ValueError:Input size must be at least 48 x 48;"
                message += " got `input_shape=" + str(
                    self.m_train_generator.image_shape) + "'"
                print(message)
                raise err

        elif pretrained_model == 'inception':
            model_base, output = self.get_pretrained_model(
                pretrained_model, weights, include_top)
            # classification block
            x = GlobalAveragePooling2D()(output)
            x = Dense(Number_FC_Neurons, activation='relu', name="fc1")(x)

        elif pretrained_model == 'xception':
            model_base, output = self.get_pretrained_model(
                pretrained_model, weights, include_top)
            # classification block
            x = Dense(Number_FC_Neurons, activation='relu',
                      name="fc1")(output)  # new FC layer, random init

        elif pretrained_model == 'resnet50':
            model_base, output = self.get_pretrained_model(
                pretrained_model, weights, include_top)
            x = Flatten(name='flatten')(output)
            x = Dropout(0.5)(x)

        elif pretrained_model == 'vgg16' or pretrained_model == 'vgg19':
            model_base, output = self.get_pretrained_model(
                pretrained_model, weights, include_top)
            # classification block
            x = Flatten()(output)
            x = Dense(4096, activation='relu')(x)
            x = Dropout(0.5)(x)
            x = Dense(4096, activation='relu')(x)
            x = Dropout(0.5)(x)

        else:
            print("Neural network not available")
            sys.exit()

        # common output layer - predictions
        predictions = Dense(self.m_num_classes,
                            activation='softmax',
                            name="predictions")(x)
        # create model instance
        self.m_model = Model(inputs=model_base.inputs, outputs=predictions)
        # Layers - set trainable parameters
        print("Total layers: {:10d}".format(len(self.m_model.layers)))
        if trainable_parameters:
            if 0 < num_trainable_parameters < 1.0:
                layers2freeze = int(
                    len(self.m_model.layers) * num_trainable_parameters) + 1
                for layer in self.m_model.layers[:layers2freeze]:
                    layer.trainable = False
                for layer in self.m_model.layers[layers2freeze:]:
                    layer.trainable = True
            else:
                for layer in self.m_model.layers:
                    layer.trainable = False

        # compile the  model
        if self.m_num_classes == 2:
            self.m_model.compile(optimizer=SGD(lr=self.m_lr, momentum=0.9),
                                 loss='categorical_crossentropy',
                                 metrics=['accuracy'])
            # store configuration compiler
            self.m_config["optimizer"] = "SGD"
            self.m_config["momentum"] = 0.9
            self.m_config["loss"] = 'categorical_crossentropy'
            self.m_config["metrics"] = ['accuracy']
        else:
            self.m_model.compile(optimizer='adam',
                                 loss='categorical_crossentropy',
                                 metrics=['accuracy'])
            # store configuration compiler
            self.m_config["optimizer"] = 'adam'
            self.m_config["momentum"] = 0  # not set
            self.m_config["loss"] = 'categorical_crossentropy'
            self.m_config["metrics"] = ['accuracy']

        # print model structure diagram
        print(self.m_model.summary())
        return self

    def __export_configuration(self, dest_dir, filename):
        """
        eport data of configuration and label for prediciton
        :param filename: (str) filename
        """
        outfile = os.path.join(dest_dir, "config_{:s}.json".format(filename))
        with open(outfile, 'w') as fp:
            json.dump(self.m_config, fp, indent=4)

    def __del__(self):
        del self.m_model
        del self.m_train_generator
        del self.__spin
Esempio n. 5
0
 def __init__(self):
     self.__spin = Spinner()
     self._model = None
     self._config = None
Esempio n. 6
0
class KerasNeuralNetwork(object):
    """
    KerasNeuralNetwork class is used to read a neural network model trained with
    Keras and provides several methods for importing a file in format:
     - '.model';
     - '.h5';
     - '.json'.
    Furthermore, before starting a new prediction, fill out the model according
    to the parameters used during the training.
    """

    def __init__(self):
        self.__spin = Spinner()
        self._model = None
        self._config = None

    def __str__(self):
        return "KerasNeuralNetwork"

    def set_model_from_file(self, filename, weights_file=None, config_compiler=None):
        """
        Read from file the correct model.
        :param filename: (str) model file model path
        :param weights_file: (str) weight file path - optional
        :param config_compiler: (str) configuration from training - optional
        """
        self.__load_model_from_file(filename, weights_file)
        self._config = config_compiler

    def __compile_keras_model(self):
        """
        Before you will predict the result for a new given input you have to
        invoke compile method.
        After compiling, you're done to deal with new images.
        _config -> tuple
        _config[0] = compiler name
        _config[1] = learning rate
        _config[2] = momentum
        _config[3] = loss category
        _config[4] = metrics
        """
        if self._config[0] == 'SGD':
            self._model.compile(optimizer=SGD(lr=self._config[1], momentum=self._config[2]),
                                loss=self._config[3],
                                metrics=self._config[4])
        else:
            self._model.compile(optimizer=self._config[0], loss=self._config[3], metrics=self._config[4])

        return self

    def __load_model_from_file(self, filename, weights_file=None):
        """
        Import trained model store as 1 file ('.model', '.h5')
        Or import the schema model in format 'json' and weights's file in
        format h5.
        :param filename: (str) pass path model file
        :param weights_file: (str) pass path weights file
        """
        if os.path.exists(filename) and weights_file is None:
            print("Loading model, please wait")
            self.__spin.start()

            # load entire model
            if filename.endswith(('.model', '.h5')):
                self._model = load_model(filename)
                self.__spin.stop()
                print("Done")

            else:
                self.__spin.stop()
                raise ValueError("Invalid extension, supported extensions are: '.h5', '.model'")

        elif os.path.exists(filename) and weights_file is not None:
            if filename.endswith('.json') and weights_file.endswith('.h5'):
                print("Loading model, please wait")
                self.__spin.start()
                # Model reconstruction from JSON file
                with open(filename, 'r') as f:
                    self._model = model_from_json(f.read())
                # Load weights into the new model
                self._model.load_weights(weights_file)
                self.__spin.stop()
                print("Done")

            else:
                raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), (filename, weights_file))

        else:
            raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), filename)

    def get_model(self):
        """
        Returns the completed keras model before start prediction
        :return: model
        """
        return self

    def predict(self, test_image):
        """
        Perform the prediction.
        :param test_image: (np-array) images in tensor form
        :return: (np-array) the probability for each class
        """
        self.__compile_keras_model()
        result = self._model.predict(test_image)
        print(result)
        return result[0]

    def _clean(self):
        pass

    def __del__(self):
        del self.__spin
        del self._model
Esempio n. 7
0
class KerasToNCSGraph(object):
    model_ = None  # store model
    tf_model_ = None  # tensorflow meta file graph structure
    base_dir = './ModelGraph'
    tf_model_dir = base_dir + '/tf_model/'  # folder tensorflow model
    graph_dir = base_dir + '/graph_model/'  # folder graph model

    def __init__(self):
        print("Prepare conversion form Keras model to Graph model")
        self.__delete_tmp_directory()
        if not os.path.exists(self.base_dir):
            print("make directory: '{:s}'".format(self.base_dir))
            os.makedirs(self.base_dir)
        if not os.path.exists(self.tf_model_dir):
            print("make directory: '{:s}'".format(self.tf_model_dir))
            os.makedirs(self.tf_model_dir)
        if not os.path.exists(self.graph_dir):
            print("make directory: '{:s}'".format(self.graph_dir))
            os.makedirs(self.graph_dir)

        self.output_layer_name = ""
        self.input_layer_name = ""
        self.wait = Spinner()
        self.lock = threading.Lock()

    def set_keras_model_file(self,
                             model_file='',
                             weights_file=None,
                             view_summary=False):
        """
        Import trained model files.
        :param model_file (str) path to file model import 'json' or model ('.model', '.h5')
        :param weights_file (str) path to file h5 import weights model
        :param view_summary (bool) print on screen the model's summary
        """

        if os.path.exists(model_file) and weights_file is None:
            self.wait.start()
            self.lock.acquire()
            try:
                if model_file.endswith((".h5", ".model")):
                    self.model_ = load_model(model_file)
            except IOError as err:
                print("Could not read file:", model_file)
                sys.exit(err)
            self.lock.release()
            self.wait.stop()
            print("Done")
        elif os.path.exists(model_file) and weights_file is not None:
            self.wait.start()
            self.lock.acquire()
            try:
                if os.path.exists(model_file) and model_file.endswith(".json"):
                    with open(model_file, 'r') as model_input:
                        model = model_input.read()
                        self.model_ = model_from_json(model)
            except IOError as err:
                print("Could not read file: ", model_file)
                sys.exit(err)
            try:
                if os.path.exists(weights_file) and weights_file.endswith(
                        ".h5"):
                    self.model_.load_weights(weights_file)  # load weights
            except IOError as err:
                print("Could not read file: ", weights_file)
                sys.exit(err)
            self.lock.release()
            self.wait.stop()
            print("Done")
            return
        else:
            print("No files found")
            sys.exit(0)

        if view_summary:
            print('Model Summary:',
                  self.model_.summary())  # print summary model

    def convertGraph(self, numoutputs=1, prefix='k2tfout', name='model'):
        """
        Converts an HD5F file to a .pb file for use with Tensorflow.
        :param  numoutputs (int)
        :param  prefix (str) the prefix of the output aliasing
        :param  name (str) the name of ProtocolBuffer file
        """
        print("Start conversion in Protocol Buffer")
        filename = name + '.pb'
        kbe.set_learning_phase(0)
        net_model = self.model_
        # Alias the outputs in the model - this sometimes makes them easier to access in TF
        pred = [None] * numoutputs
        pred_node_names = [None] * numoutputs
        for i in range(numoutputs):
            pred_node_names[i] = prefix + '_' + str(i)
            pred[i] = tf.identity(net_model.output[i], name=pred_node_names[i])
        print('Output nodes names are: ', pred_node_names)
        if len(pred_node_names) == 1:
            self.output_layer_name = pred_node_names[0]

        sess = kbe.get_session()

        # Write the graph in human readable
        f = 'graph_def_for_reference.pb.ascii'
        tf.train.write_graph(sess.graph.as_graph_def(),
                             self.tf_model_dir,
                             f,
                             as_text=True)
        print('Saved the graph definition in ascii format at: ',
              os.path.join(self.tf_model_dir, f))

        # Write the graph in binary .pb file
        constant_graph = graph_util.convert_variables_to_constants(
            sess, sess.graph.as_graph_def(), pred_node_names)
        graph_io.write_graph(constant_graph,
                             self.tf_model_dir,
                             filename,
                             as_text=False)
        print('Saved the constant graph (ready for inference) at: ',
              os.path.join(self.tf_model_dir, filename))
        self.tf_model_ = os.path.join(self.tf_model_dir, filename)
        # compile
        self.__compile_graph_model(name_graph_model_file=name)

    def __compile_graph_model(self, name_graph_model_file='model'):
        """
        Compile graph model for Neural Compute Stick (Intel Movidius) starting from Tensorflow model.
        :param name_graph_model_file (str) assign name of model exported
        """
        graph_model = self.graph_dir
        graph_model += name_graph_model_file + '.graph'  # complete graph file model (path + name)
        # assemble command
        cmd = 'mvNCCompile {0} -s 12 -in {1} -on {2} -o {3}'.format(
            self.tf_model_, 'input_1', self.output_layer_name, graph_model)
        print(cmd)
        # start compile
        os.system(cmd)

    def __delete_tmp_directory(self):
        if os.path.exists(self.base_dir):
            print("removing previous temporary files")
            shutil.rmtree(self.base_dir, ignore_errors=True)

    @staticmethod
    def title():
        print(
            "     )                                                           "
        )
        print(
            "  ( /(                    )                                    ) "
        )
        print(
            "  )\()) (  (      )    ( /(             (  ( (      )       ( /( "
        )
        print(
            "|((_)\ ))\ )(  ( /( (  )(_))(     (  (  )\))()(  ( /( `  )  )\())"
        )
        print(
            "|_ ((_)((_|()\ )(_)))\((_)  )\ )  )\ )\((_))(()\ )(_))/(/( ((_)\ "
        )
        print(
            "| |/ (_))  ((_|(_)_((_)_  )_(_/( ((_|(_)(()(_|(_|(_)_((_)_\| |(_)"
        )
        print(
            "| ' </ -_)| '_/ _` (_-</ /| ' \)) _|(_-< _` | '_/ _` | '_ \) ' \ "
        )
        print(
            "|_|\_\___||_| \__,_/__/___|_||_|\__|/__|__, |_| \__,_| .__/|_||_|"
        )
        print(
            "                                     |___/         |_|         \n"
        )

    def __del__(self):
        del self.model_
        del self.tf_model_