示例#1
0
    def __init__(self,
                 learning_rate=0.00005,
                 activation="softmax",
                 loss="categorical_crossentropy",
                 min_value_count=500,
                 per_class=527):
        self.learning_rate = learning_rate
        self.activation = activation
        self.loss = loss
        self.number_of_classes = 15
        self.min_value_count = min_value_count
        self.per_class = per_class

        self.classifier = Classifier(self.number_of_classes,
                                     self.learning_rate, self.activation,
                                     self.loss)
        self.apparel_data = ApparelDataset(app_config['DATA_LABEL_PATH'],
                                           app_config['DATA_IMAGE_ROOT'])

        self.model = self.classifier.get_model()

        self.candidate_meta = self.apparel_data.get_candidate_meta(
            min_value_count, per_class)
        self.data_processor = Preprocessing(self.candidate_meta)
        self.data_processor.move_image()
        self.validation_data_generator = self.data_processor.get_data_generator(
            'validation')
        self.train_data_generator = self.data_processor.get_data_generator(
            'train')
        self.test_data_generator = self.data_processor.get_data_generator(
            'test')
示例#2
0
    def __init__(self, learning_rate=0.00005, activation="softmax", loss="categorical_crossentropy",
                 min_value_count=500, per_class=527):
        """
        Initiate new model(classifier) instance

        :param learning_rate: learning rate of the model, default is 0.00005
        :param activation: activation function of the prediction layer, default is 'softmax'
        :param loss: loss function of the classifier, default is 'categorical_crossentropy'
        :param min_value_count: at least how much a class have to have training data, default is 500
        :param per_class: at most how much data from each class should the model take to train and test, default is 527
        """
        self.learning_rate = learning_rate
        self.activation = activation
        self.loss = loss
        self.number_of_classes = 15
        self.min_value_count = min_value_count
        self.per_class = per_class

        self.classifier = Classifier(self.number_of_classes, self.learning_rate, self.activation, self.loss)
        self.apparel_data = ApparelDataset(app_config['DATA_LABEL_PATH'], app_config['DATA_IMAGE_ROOT'])

        self.model = self.classifier.get_model()

        self.candidate_meta = self.apparel_data.get_candidate_meta(min_value_count, per_class)
        self.data_processor = Preprocessing(self.candidate_meta)
        self.data_processor.move_image()
        self.validation_data_generator = self.data_processor.get_data_generator('validation')
        self.train_data_generator = self.data_processor.get_data_generator('train')
        self.test_data_generator = self.data_processor.get_data_generator('test')
示例#3
0
class Inference:

    # COnstructor to initialize and load data, embedding and recommendation table of items
    def __init__(self):
        self.apparel_meta = ApparelDataset(app_config['DATA_LABEL_PATH'],
                                           app_config['DATA_IMAGE_ROOT'])
        self.embedding_model = ImageEmbedding()
        self.embedding_map = {}
        self.recommendations = []

    # Calculate embedding of all items
    def calculate_all_embeddings(self):
        for meta in self.apparel_meta.iterrows():
            self.embedding_map[meta[1]
                               ['id']] = self.embedding_model.get_embedding(
                                   meta[1]['image'])

    # Recommend items for an specific item by id
    def recommend_by_id(self, image_id):
        filtered_meta = self.apparel_meta.filter_by_id(image_id)
        if filtered_meta.shape[0] <= 0:
            print('No image found')
            return

        filtered_image_embeddings = []
        for meta in filtered_meta.iterrows():
            if meta[1]['id'] not in self.embedding_map:
                self.embedding_map[meta[1]['id']] = \
                    self.embedding_model.get_embedding(meta[1]['image'])

            filtered_image_embeddings.append(self.embedding_map[meta[1]['id']])

        query_image_embedding = [self.embedding_map[image_id]]

        sim_scores = 1 - pairwise_distances(
            query_image_embedding, filtered_image_embeddings, metric='cosine')
        sim_scores = sim_scores[0]

        self.recommendations = []
        i = 0
        for meta in filtered_meta.iterrows():
            self.recommendations.append(
                (meta[1]['id'], sim_scores[i], meta[1]['articleType']))
            i = i + 1

        self.recommendations = sorted(self.recommendations,
                                      key=lambda x: x[1],
                                      reverse=True)
        self.recommendations = self.recommendations[:10]

        return self.recommendations

    # Recommend items for an specific item by image
    def recommend_by_image(self, image_path):
        filtered_meta = self.apparel_meta.filter_by_sub_categories(['Topwear'])
        print(filtered_meta.head(5))

    # SHow recommendations through plotting figure
    def show_recommendation(self):
        utils.plot_figures(self.recommendations, nrows=2, ncols=5)
示例#4
0
 def __init__(self):
     """
     Initiate the inference instance
     """
     self.apparel_meta = ApparelDataset(app_config['DATA_LABEL_PATH'],
                                        app_config['DATA_IMAGE_ROOT'])
     self.embedding_model = ImageEmbedding()
     self.embedding_map = utils.load_from_pickle('embeddings')
     self.candidate_images_ids = utils.load_from_pickle('candidate_images')
     self.candidate_images = self.apparel_meta.filter_by_ids(
         self.candidate_images_ids)
     self.candidate_images['emb'] = self.candidate_images.apply(
         lambda row: self.embedding_map[row['id']], axis=1)
     self.recommendations = []
class EmbeddingCalculator:
    def __init__(self):
        self.apparel_meta = ApparelDataset(app_config['DATA_LABEL_PATH'],
                                           app_config['DATA_IMAGE_ROOT'])
        self.embedding_model = ImageEmbedding()
        self.embedding_map = {}
        return

    # Calculate embedding of all items
    def calculate_all_embeddings(self):
        """
            Calculate embeddings of all the images in the inventory

            :return:
        """
        self.embedding_map = {}
        all_metadata = self.apparel_meta.get_all_meta()
        for meta in all_metadata.iterrows():
            if meta[1]['id'] not in self.embedding_map:
                self.embedding_map[
                    meta[1]['id']] = self.embedding_model.get_embedding(
                        meta[1]['image'])

    def save_embeddings_to_pickle(self):
        """
        Save calculated embeddings in a pickle file

        :return:
        """
        utils.save_to_pickle(self.embedding_map, 'embeddings')

    def generate_candidate_products(self):
        """
        Generate candidate products from different gender-article group

        :return: True if successful, raise error otherwise
        """
        all_meta = self.apparel_meta.get_all_meta()
        all_meta['emb'] = all_meta.apply(
            lambda row: self.embedding_map[row['id']], axis=1)
        utils.generate_candidates(all_meta, save_as_pickle=True)
        return True
示例#6
0
class ModelTraining:
    def __init__(self,
                 learning_rate=0.00005,
                 activation="softmax",
                 loss="categorical_crossentropy",
                 min_value_count=500,
                 per_class=527):
        self.learning_rate = learning_rate
        self.activation = activation
        self.loss = loss
        self.number_of_classes = 15
        self.min_value_count = min_value_count
        self.per_class = per_class

        self.classifier = Classifier(self.number_of_classes,
                                     self.learning_rate, self.activation,
                                     self.loss)
        self.apparel_data = ApparelDataset(app_config['DATA_LABEL_PATH'],
                                           app_config['DATA_IMAGE_ROOT'])

        self.model = self.classifier.get_model()

        self.candidate_meta = self.apparel_data.get_candidate_meta(
            min_value_count, per_class)
        self.data_processor = Preprocessing(self.candidate_meta)
        self.data_processor.move_image()
        self.validation_data_generator = self.data_processor.get_data_generator(
            'validation')
        self.train_data_generator = self.data_processor.get_data_generator(
            'train')
        self.test_data_generator = self.data_processor.get_data_generator(
            'test')

    def train_model(self, epoch=10):
        train_history = self.model.fit_generator(
            self.train_data_generator,
            steps_per_epoch=None,
            epochs=epoch,
            verbose=1,
            validation_data=self.validation_data_generator)

        self.classifier.save_model_to_disk('classifier.h5')

        return train_history

    def evaluate_model(self):
        class_indices = self.validation_data_generator.class_indices
        tester = ModelTesting(self.test_data_generator, self.model)
        return tester.test_model(class_indices)

    def reset_data_processor(self):
        self.data_processor.return_image_to_inventory()
示例#7
0
class ModelTraining:
    """
    Model Training
    """

    def __init__(self, learning_rate=0.00005, activation="softmax", loss="categorical_crossentropy",
                 min_value_count=500, per_class=527):
        """
        Initiate new model(classifier) instance

        :param learning_rate: learning rate of the model, default is 0.00005
        :param activation: activation function of the prediction layer, default is 'softmax'
        :param loss: loss function of the classifier, default is 'categorical_crossentropy'
        :param min_value_count: at least how much a class have to have training data, default is 500
        :param per_class: at most how much data from each class should the model take to train and test, default is 527
        """
        self.learning_rate = learning_rate
        self.activation = activation
        self.loss = loss
        self.number_of_classes = 15
        self.min_value_count = min_value_count
        self.per_class = per_class

        self.classifier = Classifier(self.number_of_classes, self.learning_rate, self.activation, self.loss)
        self.apparel_data = ApparelDataset(app_config['DATA_LABEL_PATH'], app_config['DATA_IMAGE_ROOT'])

        self.model = self.classifier.get_model()

        self.candidate_meta = self.apparel_data.get_candidate_meta(min_value_count, per_class)
        self.data_processor = Preprocessing(self.candidate_meta)
        self.data_processor.move_image()
        self.validation_data_generator = self.data_processor.get_data_generator('validation')
        self.train_data_generator = self.data_processor.get_data_generator('train')
        self.test_data_generator = self.data_processor.get_data_generator('test')

    def train_model(self, epoch=10):
        """
        Train the model after compilation of the model

        :param epoch: number of epoch to train the model
        :return: history of the training of the model returned by fit_generator method
        """

        csv_logger = CSVLogger(os.path.join(app_config['MODEL_LOG_PATH'], 'train-log.csv'), append=True, separator=';')
        train_history = self.model.fit_generator(self.train_data_generator,
                                                 steps_per_epoch=None,
                                                 epochs=epoch,
                                                 verbose=1,
                                                 validation_data=self.validation_data_generator,
                                                 callbacks=[csv_logger])

        self.classifier.save_model_to_disk('classifier.h5')

        return train_history

    def evaluate_model(self):
        """
        Evaluate the trained model

        :return: test accuracy, dictionary of class-wise right & wrong count.
                 example - (accuracy, { 'Topwear': {'right': n, 'wrong': m } })
        """
        class_indices = self.validation_data_generator.class_indices
        tester = ModelTesting(self.test_data_generator, self.model)
        return tester.test_model(class_indices)

    def reset_data_processor(self):
        """
        Reset the inventory after training the model. Move the training/testing/validation images back to inventory root
        directory

        :return:
        """
        self.data_processor.return_image_to_inventory()
示例#8
0
class Inference:
    """
        Model Inference
    """

    # Constructor to initialize and load data, embedding and recommendation table of items
    def __init__(self):
        """
        Initiate the inference instance
        """
        self.apparel_meta = ApparelDataset(app_config['DATA_LABEL_PATH'],
                                           app_config['DATA_IMAGE_ROOT'])
        self.embedding_model = ImageEmbedding()
        self.embedding_map = utils.load_from_pickle('embeddings')
        self.candidate_images_ids = utils.load_from_pickle('candidate_images')
        self.candidate_images = self.apparel_meta.filter_by_ids(
            self.candidate_images_ids)
        self.candidate_images['emb'] = self.candidate_images.apply(
            lambda row: self.embedding_map[row['id']], axis=1)
        self.recommendations = []

    # Recommend similar items to another item in the inventory by id
    def recommend_by_id(self, image_id):
        """
        Recommend product similar to another product in the inventory.

        :param image_id: id of the  image of the query product
        :return: top 10 most similar recommended product
        """
        filtered_meta = self.apparel_meta.filter_by_id(image_id)
        if filtered_meta.shape[0] <= 0:
            print('No image found')
            return

        filtered_meta['emb'] = filtered_meta.apply(
            lambda row: self.embedding_map[row['id']], axis=1)
        self.recommendations = utils.get_top_10_similar_product(
            self.embedding_map[image_id], filtered_meta)

        return self.recommendations

    # Recommend similar items to a query image
    def recommend_by_image(self, image_path, article_type=None, gender=None):
        """
        Recommend available products similar to an unknown query product

        :param gender: gender of the product to search for
        :param article_type: article_type of the product
        :param image_path: path of the query image
        :return: top 10 most similar products
        """
        all_metadata = self.apparel_meta.get_all_meta()

        try:
            new_img_embedding = get_embeddings(image_path)
            labels = [
                'Bags', 'Belts', 'Bottomwear', 'Eyewear', 'Flip Flops',
                'Fragrance', 'Innerwear', 'Jewellery', 'Lips', 'Sandal',
                'Shoes', 'Socks', 'Topwear', 'Wallets', 'Watches'
            ]
            other_labels = [
                "Dress", "Loungewear and Nightwear", "Saree", "Nails",
                "Makeup", "Headwear", "Ties", "Accessories", "Scarves",
                "Cufflinks", "Apparel Set", "Free Gifts", "Stoles",
                "Skin Care", "Skin", "Eyes", "Mufflers", "Shoe Accessories",
                "Sports Equipment", "Gloves", "Hair", "Bath and Body",
                "Water Bottle", "Perfumes", "Umbrellas", "Wristbands",
                "Beauty Accessories", "Sports Accessories", "Vouchers",
                "Home Furnishing"
            ]

            temp_candidate_images = self.candidate_images

            if article_type is None:
                print('Classifying')
                sub_categories = classify_image(labels, other_labels,
                                                image_path)
                print(sub_categories)
                modified_metadata = all_metadata[
                    all_metadata['subCategory'].isin(sub_categories)]

            else:
                temp_candidate_images = temp_candidate_images[
                    temp_candidate_images['articleType'] == article_type]
                modified_metadata = all_metadata[all_metadata['articleType'] ==
                                                 article_type]

            if gender is not None:
                modified_metadata = modified_metadata[
                    modified_metadata['gender'] == gender]
                temp_candidate_images = temp_candidate_images[
                    temp_candidate_images['gender'] == gender]

            modified_metadata['emb'] = modified_metadata.apply(
                lambda row: self.embedding_map[row['id']], axis=1)

            gender, article_type = utils.get_article_type(
                new_img_embedding, temp_candidate_images)

            modified_candidate_metadata = modified_metadata[
                modified_metadata['gender'] == gender]
            modified_candidate_metadata = modified_candidate_metadata[
                modified_metadata['articleType'] == article_type]

            if len(modified_candidate_metadata) > 0:
                modified_metadata = modified_candidate_metadata

            print(article_type)
            self.recommendations = utils.get_top_10_similar_product(
                new_img_embedding, modified_metadata)

            # self.apparel_meta.filter_by_sub_categories(sub_categories)
            return self.recommendations

        except IOError as io_error:
            print('Invalid model file, train and save a valid model')
            return
        except ImportError as import_error:
            print('No model found, train and save the model first')
            return
        except Exception as exception:
            print('Unknown error')
            print(exception)
            return
        finally:
            print('Done...')
            return

    # SHow recommendations through plotting figure
    def show_recommendation(self):
        """
        Show the recommended products to the screen

        :return:
        """
        utils.plot_figures(self.recommendations, nrows=2, ncols=5)
        return
 def __init__(self):
     self.apparel_meta = ApparelDataset(app_config['DATA_LABEL_PATH'],
                                        app_config['DATA_IMAGE_ROOT'])
     self.embedding_model = ImageEmbedding()
     self.embedding_map = {}
     return