Exemplo n.º 1
0
class LabelEmbedding(object):
    """
		The main/useful class to implement some of the ideas in : https://hal.inria.fr/hal-00815747v1/document
		Given reasonable amout of data with dense predictions and getty tags we learn a mapping that can align them.
		arg_max( dense_predictions*W*getty_labels^T )
	"""
    def __init__(self, config_file, force=False, reduced=False):

        self.config_file = config_file
        self.init = True
        self.force = force

        self._read_configuration()
        self.init = self._verify_files()
        self.is_mat = True

        if not reduced:
            self.io = EmbeddingIO(self.cfgs['path_logging_dir'])
        else:
            self.io = EmbeddingIO(None, True, True)
            print 'Reduced functionality of Label Embedding'
        #if

        self.working_order = [(0, 'run_preprocess', self._run_preprocess),
                              (1, 'run_train', self._run_training),
                              (2, 'build_embedding', self._build_embedding),
                              (3, 'run_thresholds', self._run_thresholds),
                              (4, 'run_test', self._run_testing)]
        self.train_method = {
            'CFM': self._solve_closed_form,
            'CFM_PC': self._solve_closed_form_pc,
            'SGD': self._solve_sgd,
            'WSABIE': self._solve_wsabie,
            'CCA': self._solve_cca
        }

        lemb_mapping_keys = [d[0] for d in self.cfgs['lemb_mapping_list']]
        lemb_mapping_values = [d[1] for d in self.cfgs['lemb_mapping_list']]

        self.lemb_mapping = dict(zip(lemb_mapping_keys, lemb_mapping_values))

    #def
    """
		Check if all files and path exists.
		From yaml config file there are variables beginning with path_ 
	"""

    def prepare_for_testing(self):

        self._read_all_labels()

        if not '_PC' in self.cfgs['train_method']:
            self.W = self.io.read_weight_matrix(
                self.cfgs['npz_files_loc']['weights'])
            self.is_mat = True
            self.threshold_map, self.black_list = self.io.read_threshold_file(
                self.cfgs['npz_files_loc']['thresholds'])
            self.threshold_map = self.threshold_map.tolist()
            self.io.print_info(
                '{0}/{1} concepts are black-listed (not enough validation data)'
                .format(len(self.black_list), len(self.getty_labels)))
        else:
            self.W = self.io.read_all_emb(
                self.getty_labels, self.cfgs['train_method'],
                self.cfgs['npz_files_loc']['weights'])
            self.is_mat = False
            if self.cfgs['use_global_threshold']:
                self.threshold_map, self.black_list = {
                    c: 0.5
                    for c in self.W.keys()
                }, []
            else:
                self.threshold_map, self.black_list = self.io.read_threshold_file(
                    self.cfgs['npz_files_loc']['thresholds'])
            #if
            self.not_black_list = self.io.read_getty_labels(
                self.cfgs['path_getty_label_file'],
                self.cfgs['minimum_samples_for_validation'],
                self.cfgs['getty_key_words_types'])
        #if

        if self.is_mat:
            assert self.W.shape[1] == len(self.getty_labels)
            self.io.print_info('Found weight {0}x{1} matrix'.format(
                self.W.shape[0], self.W.shape[1]))
        #if

    def init_embedding(self, hedger_file, synset_names, getty_file,
                       emb_weights_file, emb_threshold_file):

        self.all_wn_labels = self.io.read_hedged_labels(hedger_file)
        self.leaf_wn_labels = synset_names

        self.getty_labels = self.io.read_getty_labels(
            getty_file, self.cfgs['getty_stop_list'],
            self.cfgs['getty_key_words_types'])

        print('Reading label embedding from {0}'.format(emb_weights_file))

        if not '_PC' in self.cfgs['train_method']:
            self.W = self.io.read_weight_matrix(emb_weights_file)
            self.is_mat = True
            self.threshold_map, self.black_list = self.io.read_threshold_file(
                emb_threshold_file)
            self.threshold_map = self.threshold_map.tolist()
            self.io.print_info(
                '{0}/{1} concepts are black-listed (not enough validation data)'
                .format(len(self.black_list), len(self.getty_labels)))
        else:

            self.W = self.io.read_all_emb(self.getty_labels,
                                          self.cfgs['train_method'],
                                          emb_weights_file)
            self.is_mat = False

            if self.cfgs['use_global_threshold']:
                self.threshold_map, self.black_list = {
                    c: 0.5
                    for c in self.W.keys()
                }, []
            else:
                self.threshold_map, self.black_list = self.io.read_threshold_file(
                    self.cfgs['npz_files_loc']['thresholds'])
            #if

            self.not_black_list = self.io.read_getty_labels(
                getty_file, self.cfgs['minimum_samples_for_validation'],
                self.cfgs['getty_key_words_types'])
        #if

        if self.is_mat:
            assert self.W.shape[1] == len(self.getty_labels)
            self.io.print_info('Found weight {0}x{1} matrix'.format(
                self.W.shape[0], self.W.shape[1]))
        #if

        self.io.print_info('Testing set-up for label embedding')

    #if

    def _verify_files(self):

        flag = True

        paths_to_check = [(k, v) for k, v in self.cfgs.items() if 'path_' in k]

        for var, file_path in paths_to_check:

            if type(file_path) == dict:
                check_files = [(var + '+' + r, j)
                               for r, j in file_path.items()]
            else:
                check_files = [(var, file_path)]
            #if

            file_flag = [os.path.exists(f[1]) for f in check_files]
            flag = flag and np.all(file_flag)

            for idx, f in enumerate(file_flag):
                if not f:
                    print colored(
                        '[WARN] Could not find {0} for {1}, no such file or directory'
                        .format(check_files[idx][1],
                                check_files[idx][0]), 'blue')
                #if
            #if

        #def

        return flag

    #def
    """
		Simple yaml config file reader
	"""

    def _read_configuration(self):

        pfile = open(self.config_file)
        self.cfgs = yaml.load(pfile)
        pfile.close()

    #def
    """
		Read wordnet synset file and getty labels. 
	"""

    def _read_all_labels(self):

        self.leaf_wn_labels, self.all_wn_labels = self.io.read_wn_labels(
            self.cfgs['path_bet_file'], self.cfgs['path_wn_labels_file'])
        self.getty_labels = self.io.read_getty_labels(
            self.cfgs['path_getty_label_file'], self.cfgs['getty_stop_list'],
            self.cfgs['getty_key_words_types'])

    #def

    def get_to_work(self, tasks):

        for idx, action, action_func in self.working_order:
            if tasks[action]:
                action_func()
            #if
        #for

    #def
    """
		Read all possible labels wordnet and getty
		Run converting dense prediction vectors from DL into histogram features. 
		Run converting getty labels into binary vectors (presense or absence)
		Save processed vectors. 
	"""

    def _run_preprocess(self):

        self._read_all_labels()
        self._read_training_samples()
        self._process_vectors()

    #def
    """
		Second step after pre-processing vectors, depending on training method selected used closed form solution or use SGD
	"""

    def _run_training(self):

        if self.cfgs['train_method'] in self.train_method.keys():
            self.train_method[self.cfgs['train_method']]()
        else:
            self.io.print_error(
                'Could not find the specified training method {0}'.format(
                    self.cfgs['train_method']))
        #if

    #def

    def _build_embedding(self):

        self._read_all_labels()

        W = self.io.read_all_emb(self.getty_labels, self.cfgs['train_method'],
                                 self.cfgs['path_weight_matrix'])

        self.io.write_all_emb(self.cfgs['npz_files_loc']['weights'], W)

        self.io.print_info('Done writing {1} embeddings to {0}'.format(
            self.cfgs['npz_files_loc']['weights'], len(W.keys())))

    #def
    """
		Run testing woudl included and instance of FullConvNet and dense predictions.
		Mapping predictions using learned weight matrix.
		Save Mapped predictions. 
		TODO : Check code to reflect changes for individual embeddings
	"""

    def _run_thresholds(self):

        self.prepare_for_testing()

        self.validation_samples = self.io.read_images(
            self.cfgs['path_file_list']['val'])
        D_val, G_val, _ = self._read_all_data(self.validation_samples, 'val')

        G_val_pred = [
            v.predict_proba(D_val)[:,
                                   np.where(v.named_steps['train'].classes_ ==
                                            1)[0][0]]
            if type(v) == sklearn.pipeline.Pipeline else
            v.predict_proba(D_val)[:, np.where(v.classes_ == 1)[0][0]]
            for k, v in self.W.items()
        ]

        G_val_pred = np.array(G_val_pred).transpose()

        sample_range = np.array(range(1, D_val.shape[0] + 1), dtype=float)

        concepts_threshold = {}
        non_trained_concepts = []

        for l in range(D_val.shape[1]):

            gt_l = np.where(G_val[:, l] > 0)[0].tolist()

            if len(gt_l) < self.cfgs['minimum_samples_for_validation']:
                self.io.print_warning(
                    'Skipping {0}, not enough samples {1}'.format(
                        self.getty_labels[l], len(gt_l)))
                non_trained_concepts.append(self.getty_labels[l])
                continue
            #if

            sorted_idx = np.argsort(-G_val_pred[:, l])

            good_idx = [1 if idx in gt_l else 0 for idx in sorted_idx.tolist()]
            c_sum = np.cumsum(np.array(good_idx)) / sample_range

            here = np.where(c_sum > self.cfgs['concept_precision'])[0].tolist()
            fhere = here[-1] if not here == [] else np.argmax(c_sum)

            concepts_threshold[self.getty_labels[l]] = G_val_pred[
                sorted_idx[fhere], l]
            self.io.print_info('Concept {0} has threshold {1}'.format(
                self.getty_labels[l],
                concepts_threshold[self.getty_labels[l]]))

        #for

        self.io.save_threshold_file(self.cfgs['npz_files_loc']['thresholds'],
                                    concepts_threshold, non_trained_concepts)

    #def

    def predict(self, dense_pred):

        vec_dense = []

        for pred in dense_pred:
            vec_dense.extend(pred)
        #for

        predictions = self.dense_to_labels(vec_dense)
        predictions = [(p) for p in predictions]

        return predictions

    #def

    def resolve_label_embedding(self, emb_pred):

        filtered_pred = [
            d[0] for d in emb_pred if d[0] not in self.cfgs['stop_list_lemb']
        ]

        mapped_pred = self.map_lemb_concepts(filtered_pred)

        return mapped_pred

    #def

    def map_lemb_concepts(self, concepts):

        return [
            self.lemb_mapping[c] if c in self.lemb_mapping.keys() else c
            for c in concepts
        ]

    #def

    def resolve_antonyms(self, human_predictions):

        conflicting_predictions = []
        human_dict = {d[0]: d[1] for d in human_predictions}

        human_labels = [d[0] for d in human_predictions]
        human_scores = [d[1] for d in human_predictions]

        for c1, c2 in self.cfgs['antonym_list']:

            if not (c1 in human_labels and c2 in human_labels):
                continue
            #if

            s1, s2 = human_dict[c1], human_dict[c2]
            idx = human_labels.index(c2) if s1 > s2 else human_labels.index(c1)

            print 'Supressing {0}:{1}'.format(human_labels[idx],
                                              human_scores[idx])

            del human_labels[idx]
            del human_scores[idx]

        #for

        remove_flag = -1

        for idx, group in enumerate(self.cfgs['count_order_list']):

            _this = np.intersect1d(human_dict.keys(), group)

            if len(_this) > 0:
                remove_flag = idx + 1
                break
            #if

        #for

        if not remove_flag == len(self.cfgs['count_order_list']):

            remove_tags = []

            for g in self.cfgs['count_order_list'][remove_flag:]:
                remove_tags.extend(g)
            #for

            for t in remove_tags:

                if not t in human_labels:
                    continue
                #if

                ridx = human_labels.index(t)

                del human_labels[ridx]
                del human_scores[ridx]

            #for

        #if

        return [(g, s) for g, s in zip(human_labels, human_scores)]

    #def

    def softmax(self, w, t=1.0):

        e = np.exp(w / t)
        dist = e / np.sum(e)
        return dist

    #def

    def dense_to_labels(self, vec_dense):

        if vec_dense == []:
            return []
        #def

        f_vec_dense = self._build_wn_label_vectors(vec_dense)

        if self.is_mat:
            getty_like_vec = np.dot(f_vec_dense, self.W)
            good = np.argsort(-getty_like_vec)
            good_labels = [
                (self.getty_labels[g], getty_like_vec[g]) for g in good
                if (not self.getty_labels[g] in self.black_list
                    and self.getty_labels[g] in self.threshold_map.keys())
            ]
            good_labels = [(g, s) for g, s in good_labels
                           if s >= 0][:self.cfgs['top_k_tags']]
        else:
            getty_like_vec = [(k, v.predict_proba(f_vec_dense)[0][np.where(
                v.named_steps['train'].classes_ == 1)[0][0]])
                              if type(v) == sklearn.pipeline.Pipeline else
                              (k, v.predict_proba(f_vec_dense)[0][np.where(
                                  v.classes_ == 1)[0][0]])
                              for k, v in self.W.items()]
            good = np.argsort(-np.array([d[1] for d in getty_like_vec]))
            good_labels = [
                getty_like_vec[g] for g in good
                if getty_like_vec[g][0] in self.not_black_list
            ]
            good_labels = [
                (g, s) for g, s in good_labels if s > self.threshold_map[g]
            ][:self.cfgs['top_k_tags']]
        #if

        return good_labels

    #for

    def _run_testing(self):

        if not os.path.exists(self.cfgs['npz_files_loc']['weights']):
            self.io.print_error(
                'Could not find label emdbedding matrix file {}'.format(
                    self.cfgs['npz_files_loc']['weights']))
            return
        #if

        self.prepare_for_testing()
        self.testing_samples = self.io.read_images(
            self.cfgs['path_file_list']['test'])

        self.io.print_info('Will process {0} test images'.format(
            len(self.testing_samples)))

        shuffle(self.testing_samples)
        #self.testing_samples = self.testing_samples[110:120]

        for idx, sample in enumerate(self.testing_samples):

            if idx % 1000 == 0:
                self.io.print_info('Processing {0}/{1} image'.format(
                    idx, len(self.testing_samples)))
            #if

            basename = os.path.basename(sample)
            basename, ext = os.path.splitext(basename)

            json_file = os.path.join(self.cfgs['path_results_dir']['test'],
                                     basename + '.json')

            if os.path.exists(json_file):
                if not self.force:
                    self.io.print_warning(
                        'Skipping {0}, already exists'.format(json_file))
                    continue
                #if
            #if

            vec_dense = self.io.read_vector(
                os.path.join(self.cfgs['path_dense_pred_loc']['test'],
                             basename) + self.cfgs['wn_suffix'])
            vec_getty = self.io.read_vector(
                os.path.join(self.cfgs['path_getty_labels_loc']['test'],
                             basename) + self.cfgs['getty_suffix'])

            good_labels = self.dense_to_labels(vec_dense)

            self.io.save_good_labels(json_file, dict(good_labels))

            if self.cfgs['show_predicted_labels']:
                self.io.print_info('Photo-id {0}'.format(basename))
                self.io.print_info('Predicted {0}'.format(good_labels))
                self.io.print_warning('GT {0}'.format(vec_getty))
            #if

        #for

    #def
    """
		Read images pointed to by training and validation file lists
	"""

    def _read_training_samples(self):

        self.training_data = {}
        self.validation_data = {}

        self.training_data['samples'] = self.io.read_images(
            self.cfgs['path_file_list']['train'])
        self.validation_data['samples'] = self.io.read_images(
            self.cfgs['path_file_list']['val'])

        self.io.print_info(
            'Found {0} training samples {1} validation samples'.format(
                len(self.training_data['samples']),
                len(self.validation_data['samples'])))

    #def
    """
		Convert dense predictions into vectors
		Convert getty labels into binary vectors
	"""

    def _process_vectors(self):

        self._label_to_vectors(self.training_data['samples'], 'train')
        self._label_to_vectors(self.validation_data['samples'], 'val')

    #def

    def _label_to_vectors(self, training_images, tag='train'):

        for idx, sample in enumerate(training_images):

            if idx % 1000 == 0:
                self.io.print_info(
                    'Processing {0}/{1} vectors for {2}, {3}'.format(
                        idx, len(training_images), tag, sample))
            #if

            basename = os.path.basename(sample)
            basename, ext = os.path.splitext(basename)

            npz_file = os.path.join(self.cfgs['path_processed_vectors'][tag],
                                    basename + '.npz')

            if (os.path.exists(npz_file) and not self.force):
                self.io.print_info(
                    'Skipping {0}, already exists'.format(npz_file))
                continue
            #if

            vec_dense = self.io.read_vector(
                os.path.join(self.cfgs['path_dense_pred_loc']['train'],
                             basename) + self.cfgs['wn_suffix'])
            vec_getty = self.io.read_vector(
                os.path.join(self.cfgs['path_getty_labels_loc']['train'],
                             basename) + self.cfgs['getty_suffix'])

            #f_vec_dense = vec_dense

            f_vec_dense = self._build_wn_label_vectors(vec_dense)
            f_vec_getty = self._build_getty_label_vectors(vec_getty)

            self.io.save_npz_file(f_vec_dense, f_vec_getty, npz_file)

        #for

        self.io.print_info('Done building {0} vectors'.format(tag))

    #def
    """
		Convert wn dense predictions to sparse vectors and L2 normalization. 
	"""

    def _build_wn_label_vectors(self, svec):

        if svec == []:
            return []
        #if

        vec = np.zeros(len(self.leaf_wn_labels), dtype=float)

        idx = np.array([d[0] for d in svec])
        values = np.array([d[1] for d in svec])

        for d in svec:
            vec[d[0]] += d[1]
        #if

        if not self.cfgs['normalization']['wn_norm'] == 'None':
            vec /= (np.linalg.norm(vec) + 0.000001)
        #if

        return vec

    #def
    """
		Convert getty label vectors to binary vectors of presense of absence and L2 normalization. 
	"""

    def _build_getty_label_vectors(self, svec):

        if svec == []:
            return []
        #if

        vec = np.zeros(len(self.getty_labels), dtype=float)
        idx = np.array([
            self.getty_labels.index(d) for d in svec if d in self.getty_labels
        ])

        if idx.size == 0:
            return []
        #if

        vec[idx] = 1.0

        if not self.cfgs['normalization']['getty_norm'] == 'None':
            vec /= (np.linalg.norm(vec) + 0.000001)
        #if

        return vec

    #def

    def _init_embedding_matrix(self):

        self.W = np.zeros((len(self.leaf_wn_labels), len(self.getty_labels)))
        self.io.print_info('Weight matrix set-up {0}x{1}'.format(
            self.W.shape[0], self.W.shape[1]))

    #def

    def _init_identity_matrix(self):

        self.I = np.eye(len(self.leaf_wn_labels), len(self.leaf_wn_labels))

    #def

    def _read_all_data(self, image_list, tag):

        D_all_vec = []
        G_all_vec = []
        all_files = []

        for idx, sample in enumerate(image_list):

            if idx % 1000 == 0:
                self.io.print_info(
                    'Reading {0}/{1} vectors for {3}, {2}'.format(
                        idx, len(image_list), sample, tag))
            #if

            basename = os.path.basename(sample)
            basename, ext = os.path.splitext(basename)

            npz_file = os.path.join(self.cfgs['path_processed_vectors'][tag],
                                    basename + '.npz')

            if not os.path.exists(npz_file):
                self.io.print_warning(
                    'Skipping {0} no such file'.format(npz_file))
                continue
            #if

            D, G = self.io.read_npz_file(npz_file)

            D = D.flatten()

            if (D.size == 0 or G.size == 0
                    or not len(D) == self.cfgs['expected_dim']):
                self.io.print_warning(
                    'Skipping {0} mis-match of dimensionality'.format(
                        npz_file))
                continue
            #if

            D_all_vec.append(D)
            G_all_vec.append(G)
            all_files.append(basename)

        #for

        return np.array(D_all_vec), np.array(G_all_vec), all_files

    #def
    """
		Different solutions to label embedding Closed form solution (CFM) / SGD / WSABIE / CCA
	"""

    def _solve_closed_form(self):

        self._read_all_labels()
        self._read_training_samples()

        #self._init_embedding_matrix()
        self._init_identity_matrix()

        D_train, G_train, _ = self._read_all_data(
            self.training_data['samples'], 'train')

        if self.cfgs['balance_data']:
            D_train, G_train = self._balance_training_data(D_train, G_train)
        #if

        D_val, G_val, _ = self._read_all_data(self.validation_data['samples'],
                                              'val')

        train_size = (D_train.nbytes + G_train.nbytes) / (1000.0 * 1024**2)
        val_size = (D_val.nbytes + G_val.nbytes) / (1000.0 * 1024**2)

        # TODO : compute expected size of data in memory before reading it LOL
        # TODO : Future harsimrat will fix this
        # Yo future Harsimrat here, this is obsolte now.

        self.io.print_info('Train : {0:2f} GB, val : {1:2f} GB'.format(
            train_size, val_size))

        for l in self.cfgs['lambda']:

            self.io.print_info(
                'Computing closed form solution (CFM) for lambda = {0}'.format(
                    l))
            self.W = np.dot(
                np.linalg.inv(
                    np.dot(D_train.transpose(), D_train) + l * self.I),
                np.dot(D_train.transpose(), G_train))

            error = 1 - self._compute_validation_error_on_tags(
                self.W, D_val, G_val)

            self.io.print_info('(CFM) error for lambda = {0} : {1}'.format(
                l, error))
            self.io.save_weight_matrix(
                self.W,
                os.path.join(self.cfgs['path_weight_matrix'],
                             'CFM-{0}.npz'.format(l)))

        #for

    #def
    """
		Closed form solution per concepts
	"""

    def _solve_closed_form_pc(self):

        self._read_all_labels()
        self._read_training_samples()

        D_train, G_train, train_files = self._read_all_data(
            self.training_data['samples'], 'train')
        D_val, G_val, val_files = self._read_all_data(
            self.validation_data['samples'], 'val')

        train_size = (D_train.nbytes + G_train.nbytes) / (1000.0 * 1024**2)
        val_size = (D_val.nbytes + G_val.nbytes) / (1000.0 * 1024**2)

        self.io.print_info('Train : {0:2f} GB, val : {1:2f} GB'.format(
            train_size, val_size))
        self.reset_pipe_line()

        for label, label_name in len(self.getty_labels):

            svm_file_path = os.path.join(self.cfgs['path_weight_matrix'],
                                         'CFM_PC-{0}.pkl'.format(label_name))

            if os.path.exists(svm_file_path):
                if not self.force:
                    self.io.print_warning(
                        'Skipping {}, already exists'.format(svm_file_path))
                    continue
                #if
            #if

            tidx = np.sum(G_train[:, label])
            vidx = np.sum(G_val[:, label])

            if tidx == 0 or vidx == 0:
                self.io.print_warning(
                    'Not enough samples for {0}, train:{1} or val :{2}'.format(
                        label_name, int(tidx), int(vidx)))
                continue
            #if

            self.io.print_info(
                '{1}/{2} Learning embedding for {0} with {3} +samples {4} -ive samples'
                .format(label_name, label, len(self.getty_labels),
                        np.sum(G_train[:, label]),
                        G_train.shape[0] - np.sum(G_train[:, label])))

            self.pipe_line.fit(D_train, G_train[:, label])
            error = 1 - self.pipe_line.score(D_val, G_val[:, label])

            self.io.print_info('(CFM_PC) error for {1} : {0}'.format(
                error, label_name))

            self.io.save_emb_file(self.pipe_line, svm_file_path)

        #for

    #def

    def reset_pipe_line(self):

        action_list = [
            ('norm', normalizer_dict[self.cfgs['normalization_type']]),
            ('scale', scaling_dict[self.cfgs['scaling_type']]),
            ('train', classifier_dict[self.cfgs['classifier_type']])
        ]
        action_list = [(a, b) for a, b in action_list if not b == None]

        self.pipe_line = Pipeline(action_list)

    #def

    def _solve_sgd(self):

        self.io.print_error('SGD not implemented')

    #def

    def _solve_wsabie(self):

        self.io.print_error('WSABIE not implemented')

    #fef

    def _solve_cca(self):

        self.io.print_error('CCA not implemented')

    #def
    """
		Validation needs to change since we optimize for tag coverage we should compute intersecton over union of predicted tags + getty tags on validation set
	"""

    def _compute_validation_error(self, W, D, G):

        n_samples = G.shape[0]
        pG = np.dot(D, W)

        for i in range(pG.shape[0]):
            pG[i, :] /= (np.linalg.norm(pG[i, :]) + 0.000001)
        #for

        cG = np.dot(pG, G.transpose())

        predictions = np.argmax(cG, axis=0)
        gt_match = np.array(range(n_samples))

        good = np.bitwise_xor(predictions, gt_match)
        correct_match = good == 0

        return np.sum(correct_match) / (n_samples + 0.0)

    #def
    """
		This function needs to change towards what we should optimize currently global predictions of tag is optimized. 

	"""

    def _compute_validation_error_on_tags(self, W, D, G):

        pG = np.dot(D, W)

        predictions = np.zeros(pG.shape)

        for i in range(pG.shape[0]):
            pidx = np.argsort(-pG[i, :])[:self.cfgs['top_k_tags']]
            predictions[i, pidx] = 1
        #for

        gt = np.zeros(G.shape)
        idx = np.where(G > 0)
        gt[idx] = 1

        good = predictions * gt
        n_samples = np.sum(predictions)

        #self.io.print_info('{0} correct out of {1}'.format(np.sum(good),n_samples))

        return np.sum(good) / (n_samples + 0.0)

    #def

    def _compute_validation_error_on_tags_pc(self, W, D, G):

        pG = np.dot(D, W)
        predictions = np.zeros(pG.shape)

        pidx = np.where(pG > 0)[0]
        predictions[pidx] = 1

        gt = G

        good = predictions * gt
        n_samples = np.sum(predictions)

        # error : (fp + tn)/n_samples

        return (np.sum(predictions) + np.sum(gt) -
                2 * np.sum(good)) / (n_samples + 0.0)

    #def

    def _restore_snapshot(self, label_idx):

        if label_idx == 0:
            self._init_embedding_matrix()
            return
        #if

        label = labe_idx - 1
        weight_matrix_path = os.path.join(
            self.cfgs['path_weight_matrix'],
            'CFM-{1}.npz'.format(l, self.getty_labels[label]))

        self.W = self.io.read_weight_matrix(weight_matrix_path)

    #def

    def _balance_training_data(self, DL_train, G_train):

        return DL_train_balance, G_train_balance

    #def


#class
Exemplo n.º 2
0
class TheanoTester():
    def __init__(self, config_file, verbose=False, raw_predictions=False):

        if not os.path.exists(config_file):
            print 'Error : could not find config file'.format(config_file)
            self.init = False
            return

        self.tester_config_file = config_file
        self.verbose = verbose
        self.raw_predictions = raw_predictions
        self.read_config()

        self.io = EmbeddingIO(self.cfgs['log_dir'], 'testing')

        self.tester_name = self.cfgs['model_name']
        self.model_config_file = self.cfgs['model_config_file']

        self.init = False
        self.thresholds = None

        mapping_keys = [d[0] for d in self.cfgs['mapping_list']]
        mapping_values = [d[1] for d in self.cfgs['mapping_list']]

        self.mapping = dict(zip(mapping_keys, mapping_values))
        self.softpooling_func = f
        if self.tester_name not in model_dict.keys():
            self.io.print_error(
                'Not a valid model type {0} chose among {1}'.format(
                    self.tester_name, model_dict.keys()))
            self.init = False
            return

        if not os.path.exists(self.tester_config_file):
            self.io.print_error('Could not find configuration file {0}'.format(
                self.tester_config_file))
            self.init = False
            return

        self.tester = None
        self.action_items = {'test': self.run, 'eval': self.eval}
        self.test_lmdb = LMDBParser_test(self.cfgs['test_file'],
                                         log_dir=self.cfgs['log_dir'])
        self.resize_test = self.cfgs['resize_test']
        # self.load_synset_file()
        # self.test_lmdb = LMDBParser(self.cfgs['test_file'], log_dir=self.cfgs['log_dir'])
        # self.test_lmdb.set_params_test(self.concepts)
    def _read_threshold_file(self):

        if 'threshold_file' in self.cfgs.keys():

            try:

                pfile = open(self.cfgs['threshold_file'], 'r')
                thresholds = json.load(pfile)
                pfile.close()

                self.thresholds = {
                    c: thresholds[c] if c in thresholds.keys() else
                    self.cfgs['global_threshold']
                    for c in self.concepts
                }

            except Exception as err:

                self.io.print_error(
                    'Error parsing threshold file {0},{1}'.format(
                        self.cfgs['threshold_file'], err))

    def read_config(self):

        pfile = open(self.tester_config_file)
        self.cfgs = yaml.load(pfile)
        pfile.close()

    def setup(self):

        self.tester = model_dict[self.tester_name]()

        self.tester.configure(self.model_config_file)

        self.tester.define()
        #import ipdb; ipdb.set_trace()
        self.model_type = self.tester.model.get_config()['name']

        self.im_h, self.im_w = self.tester.cfgs[
            'image_height'], self.tester.cfgs['image_width']

        if not self.tester.init:
            self.io.print_error('Error with model definition')
            self.init = False
            return

        self.io.print_info('{0} Model defined from {1}'.format(
            self.tester_name, self.model_config_file))

        self.compile()

        if not self.tester.init:
            self.io.print_error('Error with model compilation')
            self.init = False
            return

        self.io.print_info('{0} Model compiled'.format(self.tester_name))

        self.init = True
        self.load_synset_file()
        self.load_mean_file()
        self._read_threshold_file()
        self.load_confidence_model()
        self.read_label_embedding()

    def compile(self):
        """
            This compile version is to be used for testing only. Since its optimized for predictions
        """

        self.output_nodes = self.cfgs['output_node_name']['test']

        if self.model_type == 'Sequential':
            self.inference = K.function(
                [self.tester.model.get_input(train=False)],
                [self.tester.model.layers[-1].get_output(train=False)])
        elif self.model_type == 'Graph':
            #import ipdb; ipdb.set_trace()
            self.inference = K.function(
                [self.tester.model.get_input(train=False)], [
                    self.tester.model.nodes[node].get_output(train=False)
                    for node in self.output_nodes
                ])
        else:
            self.io.print_error(
                'Say whaaaat ?! This model type is not supported : {}'.format(
                    self.model_type))
            sel.init = False

    def read_label_embedding(self):

        self.label_embedding = None
        self.label_vectors = None

        if 'label_embedding_file' in self.cfgs.keys():

            self.label_embedding = self.io.read_npz_file(
                self.cfgs['label_embedding_file'], 'matrix')
            self.label_vectors = self.io.read_npz_file(
                self.cfgs['label_embedding_file'], 'vectors')

            self.io.print_info('Read label embedding file {0}'.format(
                self.cfgs['label_embedding_file']))

    def load_confidence_model(self):

        self.confidence_model = None

        if 'confidence_model' in self.cfgs.keys():
            self.confidence_model = joblib.load(self.cfgs['confidence_model'])

    #to be used in
    def get_images_frVisualization(self):
        self.load_synset_file()
        GndTr = dict()
        if not self.init:
            return
        indexes = dict()
        self.test_images = self.io.read_images(self.cfgs['test_file_list'])

        #filterout images from getty
        self.io.print_info(
            'Removing getty scrapped images from validation data')

        filter_getty = [
            contains(img, 'getty-concept-sourcing') for img in self.test_images
        ]
        ind = np.where(np.array(filter_getty) == True)[0]
        test_images = np.array(self.test_images)[ind]
        #---------------

        for image in test_images:
            im_basename = os.path.basename(image)
            im_basename, img_ext = os.path.splitext(im_basename)

            g = self.test_lmdb.get_labels(im_basename)
            concepts = np.array(self.concepts)
            index = np.where(g == 1)[0]
            GndTr[im_basename] = concepts[index]
            indexes[im_basename] = index

        return (test_images, GndTr, indexes)

    def visualize_image(self, beta, pixels):
        self.beta = beta

        self.load_synset_file()

        flag, predictions, confidence, t = self.classify_images(pixels)

        #file_paths = [os.path.join(self.cfgs['results_dir'], 'visualization_',str(self.beta)+'_'+im + save_ext) for im in basenames]
    def run(self):

        self.load_synset_file()

        if not self.init:
            return

        self.test_images = self.io.read_images(self.cfgs['test_file_list'])
        image_batches = [
            self.test_images[i:i + self.cfgs['batch_size']]
            for i in range(0, len(self.test_images), self.cfgs['batch_size'])
        ]

        self.io.print_info('{0} images split into {1} Batches of {2}'.format(
            len(self.test_images), len(image_batches),
            self.cfgs['batch_size']))
        for beta in self.cfgs['betas']:
            self.beta = beta
            for idx, images in enumerate(image_batches):

                if not self.cfgs['force']:

                    flag = self.check_jsons(images)

                    if flag:
                        self.io.print_warning(
                            'Skipping batch {0} of {1}'.format(
                                idx, len(image_batches)))
                        continue

                pixels, basenames, dummy = self.fetch_images(images)
                dummy = []

                flag, predictions, confidence, t = self.classify_images(pixels)

                if self.raw_predictions is False:
                    getty_like_filter = [
                        self.suppress_stop_list(g) for g in predictions
                    ]
                    getty_like_safe = [
                        self.run_thresholds(g) for g in getty_like_filter
                    ]
                    getty_like_pc = [
                        self.map_concepts(g) for g in getty_like_safe
                    ]
                    getty_like_public = [
                        self.resolve_antonyms(g) for g in getty_like_pc
                    ]
                    getty_like_unique = [
                        self.resolve_duplicates(g) for g in getty_like_public
                    ]
                    predictions_pc = getty_like_unique
                    save_ext = '.json'
                else:
                    predictions_pc = predictions
                    save_ext = '.npz'

                if not flag:
                    continue

                file_paths = [
                    os.path.join(self.cfgs['results_dir'],
                                 str(self.beta) + '_' + im + save_ext)
                    for im in basenames
                ]

                if not self.raw_predictions:
                    to_save = [dict({'external': p}) for p in predictions_pc]
                else:
                    to_save = predictions_pc
                #import ipdb; ipdb.set_trace()

                #to_save = [dict({'external': p}) for p in predictions_pc]
                #to_save=predictions_pc
                #to_save_id = [dict({'external': id_}) for id_ in ids]
                assert (len(file_paths) == len(to_save))

                self.io.print_info('Done batch {0} of {1} in {2} secs'.format(
                    idx, len(image_batches), t))
                #import ipdb; ipdb.set_trace()
                #import ipdb; ipdb.set_trace()
                f = map(self.io.save_good_labels, file_paths, to_save)
            #f = map(self.io.save_good_labels, file_paths, to_save_id)
    def check_jsons(self, images):

        basenames = []

        for image in images:

            im_basename = os.path.basename(image)
            im_basename, _ = os.path.splitext(im_basename)

            basenames.append(im_basename)

        flags = [
            os.path.exists(os.path.join(self.cfgs['results_dir'], b + '.json'))
            for b in basenames
        ]

        return np.all(flags)

    def compare_various_betas(self):

        betas = self.cfgs['betas']
        Area_PR = dict()
        dir_path = os.path.dirname(os.path.realpath(__file__))
        #print dir_path
        self.limit_NoofClasses = None
        self.load_synset_file()
        self.load_synset_file_training()
        self.imgHist_Concepts_inTraindata = [
            (np.where(np.array(self.concepts) == i)[0][0])
            for i in self.trained_concepts
        ]

        #import lmdb
        #lmdb_env = lmdb.open("./keywording_test_images_labels", readonly=True, lock=False)

        # lmdb_txn = lmdb_env.begin()
        # read_label = lmdb_txn.get
        # label1test=self.test_lmdb.get_labels(read_label,'10085536')
        # label2test=self.test_lmdb.get_labels(read_label,'10085536')
        #self.imgname_labels=self.test_lmdb.create_keys_labels_dict()
        var = dict()
        for beta in betas:
            var.update(self.eval_usinglmdb(str(beta)))

        #import ipdb; ipdb.set_trace()
        if self.limit_NoofClasses == None:
            df2 = pd.DataFrame(var, index=self.trained_concepts)
        else:
            df2 = pd.DataFrame(
                var, index=self.trained_concepts[0:self.limit_NoofClasses])

        df2.to_csv(dir_path + '/results/' +
                   self.cfgs['results_dir'].split('/')[-2] + '.csv')
        #import ipdb; ipdb.set_trace()

        # mAP=[]
        # mRec90=[]
        # mRec80=[]
        # max_f1=[]
        # for beta in betas:
        #     vAP,v90,v80,vf1=Area_PR[beta]
        #     mAP.append(vAP)
        #     mRec90.append(v90)
        #     mRec80.append(v80)
        #     max_f1.append(vf1)
        #     #print ("mAP:%.4f,mean Recall:%.4f,beta:%s" % (mAP,mRec,str(beta)))
        # #import ipdb; ipdb.set_trace()
        # #print(*betas, sep='\t')
        # print('\t'.join([str(x) for x in betas]))
        # #print(*mRec80, sep='\t')
        # print('\t'.join([str(round(x*100,3)) for x in mRec80]))
        # #print(*mRec90, sep='\t')
        # print('\t'.join([str(round(x*100,3)) for x in mRec90]))
        # print('\t'.join([str(round(x*100,3)) for x in mAP]))
        # print('\t'.join([str(round(x*100,3)) for x in max_f1]))
        #print(*mAP, sep='\t')
        #pickle.dump(Area_PR,open('/nas2/praveen/home/rnd-libs/rnd_libs/lib/keras/result_Area_PR','wb'))

    # def generate_csv_file(self):

    #    betas=self.cfgs['betas']
    #    Area_PR=dict()

    #    #import lmdb
    #    #lmdb_env = lmdb.open("./keywording_test_images_labels", readonly=True, lock=False)
    #    #import ipdb; ipdb.set_trace()
    #    # lmdb_txn = lmdb_env.begin()
    #    # read_label = lmdb_txn.get
    #    # label1test=self.test_lmdb.get_labels(read_label,'10085536')
    #    # label2test=self.test_lmdb.get_labels(read_label,'10085536')
    #    #self.imgname_labels=self.test_lmdb.create_keys_labels_dict()

    #    for beta in betas:
    #        Area_PR[beta]=self.eval_usinglmdb(str(beta))

    #    mAP=[]
    #    mRec90=[]
    #    mRec80=[]
    #    max_f1=[]
    #    detections=[]
    #    for beta in betas:
    #        vAP,v90,v80,max_f1,detections=Area_PR[beta]
    #        mAP.append(vAP)
    #        mRec90.append(v90)
    #        mRec80.append(v80)
    #print ("mAP:%.4f,mean Recall:%.4f,beta:%s" % (mAP,mRec,str(beta)))
    #import ipdb; ipdb.set_trace()
    #print(*betas, sep='\t')

    #import ipdb; ipdb.set_trace()

    # def compare_various_betas(self):
    #     import ipdb; ipdb.set_trace()
    #     betas=self.cfgs['betas']
    #     for beta in betas:
    #         self.eval_usinglmdb(str(beta)

    def eval_usinglmdb(self, beta):

        #import ipdb; ipdb.set_trace()
        #import ipdb; ipdb.set_trace()

        self.test_images = self.io.read_images(self.cfgs['test_file_list'])

        self.predictions = {}
        self.gt = {}
        valid_keys = []
        notgoodGTimgs = []
        ImgsSmallNumofTags = []
        #import ipdb; ipdb.set_trace()

        for idx, image in enumerate(self.test_images):

            if idx % 1000 == 0:
                self.io.print_info('Reading {0}/{1}'.format(
                    idx, len(self.test_images)))

            im_basename = os.path.basename(image)
            im_basename, img_ext = os.path.splitext(im_basename)

            #result_json = os.path.join(self.cfgs['results_dir'], im_basename + '.json')
            result_json = os.path.join(self.cfgs['results_dir'],
                                       beta + '_' + im_basename + '.npz')
            #gt_json = os.path.join(self.cfgs['gt_dir'], im_basename + '.json')

            if os.path.exists(result_json):
                #p, s,ids = self.io.read_prediction_json_withIDs(result_json)
                p = np.load(result_json)['features']

            else:
                p = []
            #g = self.io.read_vector(gt_json)
            #import ipdb; ipdb.set_trace()
            g = self.test_lmdb.get_labels(im_basename)
            #print np.sum(g)
            #print p.shape
            if len(p) == 0:
                print("images with no prediction generated: %s") % im_basename
                continue

            if len(g) == 0:
                #import ipdb; ipdb.set_trace()
                print("images with no GT data: %s") % im_basename
                notgoodGTimgs.append(im_basename)
                continue
            if len(g) < 7735 and len(g) != 0:
                print("images with small number of tags: %s") % im_basename
                ImgsSmallNumofTags.append(im_basename)
                continue
            #g_filtered=self.parse_gndTruth_withFilter(ids,g)

            # if p is [] or g is []:
            #     continue

            self.predictions[im_basename] = p

            self.gt[im_basename] = g
            valid_keys.append(im_basename)
            # if idx>1000:
            #     break
        print 'Number of images: with no GT %d and with small no of tags %d' % (
            len(notgoodGTimgs), len(ImgsSmallNumofTags))
        #import ipdb; ipdb.set_trace()

        y_test = np.zeros((len(valid_keys), len(self.concepts)), dtype='u1')
        y_score = np.zeros((len(valid_keys), len(self.concepts)))

        for i, key in enumerate(valid_keys):
            y_test[i] = self.gt[key]
            y_score[i] = self.predictions[key]

        gt = dict()
        pred = defaultdict(dict)

        for i, concept in enumerate(self.concepts):
            imgname_ind = np.where(y_test[i] == 1)
            np_array_photo_ids = np.array(valid_keys)[imgname_ind]
            gt[concept] = list(np_array_photo_ids)
            #pred[concept]={key: value for key, value in self.predictions.items() if key in list(np_array_photo_ids)}
            # for key in list(np_array_photo_ids):
            #     pred[concept].update({key: self.predictions[key]})

        # pairof_photoid_predictions=self.predictions.items()
        # for photo_id, predictions in pairof_photoid_predictions:
        #     for concept, score in zip(self.concepts,predictions):
        #         pred[concept][photo_id] = score
        # #import ipdb; ipdb.set_trace()
        # thresholds=get_thresholds(pred, self.concepts, gt)
        # detections=get_detections_per_concept(pred, self.concepts, gt, thresholds)

        #class_histogram=y_test.sum(axis=0)
        #import ipdb; ipdb.set_trace()

        if self.cfgs['percentate_of_classesFrEval'] != None or self.cfgs[
                'percentate_of_classesFrEval'] < 1.0:
            use_subsetofClsFrEval = True
            n_classes = len(self.concepts)

            limit_NoofClasses = int(self.cfgs['percentate_of_classesFrEval'] *
                                    n_classes)

            subset_indices_FrEval = self.imgHist_Concepts_inTraindata[:
                                                                      limit_NoofClasses]
            self.limit_NoofClasses = limit_NoofClasses
            #self.concepts=np.array(self.concepts)[indices]

            #y_test_subset=np.zeros((len(valid_keys),len(self.concepts)),dtype='u1')
            #y_score_subset=np.zeros((len(valid_keys),len(self.concepts)))

            #for i,key in enumerate(valid_keys):
            #    y_test_subset[i]=self.gt[key][indices]
            #    y_score_subset[i]=self.predictions[key][indices]
            #print "Using %d out of %d rare number of classes for evaluations" % (limit_NoofClasses,n_classes)
        else:
            use_subsetofClsFrEval = False
            subset_indices_FrEval = self.imgHist_Concepts_inTraindata
            #subset_indices_FrEval=range(len(self.concepts))

        #if use_subsetofClsFrEval:
        #    y_test=y_test_subset
        #    y_score=y_score_subset

        #plt.plot(np.sort(temp)[::-1])

        #plt.savefig('/nas2/praveen/home/rnd-libs/rnd_libs/lib/keras/intermediate/class_histogram')

        #fpr = dict()
        #tpr = dict()
        recAt90 = []
        recAt70 = []
        ap = []
        names = ['ap', 'recAt70', 'recAt90']
        #max_f1=[]

        for ind in subset_indices_FrEval:
            #import ipdb; ipdb.set_trace()
            # if y_test[:, i].sum()==0.0:
            #     continue
            #fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_score[:, i])

            ap.append(
                roundoff(
                    average_precision_score(y_test[:, ind], y_score[:, ind])))
            recAt90.append(
                roundoff(
                    recall_at_specified_precision(y_test[:, ind],
                                                  y_score[:, ind],
                                                  specified_precision=0.9)))
            recAt70.append(
                roundoff(
                    recall_at_specified_precision(y_test[:, ind],
                                                  y_score[:, ind],
                                                  specified_precision=0.7)))
            #max_f1[self.concepts[ind]] = max_f1_score(y_test[:, ind], y_score[:, ind])

        #import ipdb; ipdb.set_trace()
        #return (np.array(ap.values()).mean(), np.array(recAt90.values()).mean(), np.array(recAt80.values()).mean())
        #max_f1=[0.0]
        #import ipdb; ipdb.set_trace()
        returndict = dict()

        for name in names:
            returndict[beta + '_' + name] = locals()[name]
        return (returndict)
        #import ipdb; ipdb.set_trace()
        # import ipdb; ipdb.set_trace()
        # list_thres=[self.cfgs['global_threshold']]
        # for t in list_thres:
        #     self.compute_precision_recall(t)
    def eval(self):

        self.load_synset_file()

        self.test_images = self.io.read_images(self.cfgs['test_file_list'])

        self.predictions = {}
        self.gt = {}

        for idx, image in enumerate(self.test_images):

            if idx % 1000 == 0:
                self.io.print_info('Reading {0}/{1}'.format(
                    idx, len(self.test_images)))

            im_basename = os.path.basename(image)
            im_basename, _ = os.path.splitext(im_basename)

            result_json = os.path.join(self.cfgs['results_dir'],
                                       im_basename + '.json')
            gt_json = os.path.join(self.cfgs['gt_dir'], im_basename + '.json')

            p, s = self.io.read_prediction_json(result_json)
            g = self.io.read_vector(gt_json)

            if p is [] or g is []:
                continue

            self.predictions[im_basename] = zip(p, s)
            self.gt[im_basename] = list(set(g).intersection(self.concepts))

        for t in [self.cfgs['thresholds']]:
            self.compute_precision_recall(t)

    def compute_precision_recall(self, thresh):

        fps = {}
        tps = {}
        fns = {}
        gt_dict = {}

        for c in self.concepts:
            fps[c], tps[c], fns[c], gt_dict[c] = [], [], [], []

        for key, value in self.predictions.items():

            detections = [v[0] for v in value if v[1] >= thresh]
            gt = self.gt[key]

            for g in gt:
                gt_dict[g].append(key)

            tp = list(set(gt).intersection(detections))
            fp = list(set(detections) - set(gt))
            fn = list(set(gt) - set(detections))

            for t in tp:
                tps[t].append(key)

            for f in fp:
                fps[f].append(key)

            for n in fn:
                fns[n].append(key)

        for c in self.concepts:

            if gt_dict[c] == []:
                self.io.print_info(
                    'Skipping {0}, no samples in ground-truth'.format(c))
                continue

            p = len(tps[c]) / (len(tps[c]) + len(fps[c]) + 0.00000001)
            r = len(tps[c]) / (len(gt_dict[c]) + 0.0)

            f1 = self.compute_f1(p, r)

            self.io.print_info(
                'At {0} : {1} precision {2}, recall {3}, f1-score {4}'.format(
                    c, thresh, p, r, f1))

    def compute_f1(self, p, r):

        return 2 * (p * r) / (p + r + 0.000001)

    def load_synset_file(self):

        pfile = open(self.cfgs['synset_file'], 'r')
        concepts = pfile.readlines()
        pfile.close()

        self.concepts = [p.strip() for p in concepts]

    def load_synset_file_training(self):

        pfile = open(self.cfgs['synset_file_training'], 'r')
        concepts = pfile.readlines()
        pfile.close()

        self.trained_concepts = [p.strip() for p in concepts]

    def load_mean_file(self):

        if not self.cfgs['mean_file'] == 'None':
            pfile = open(self.cfgs['mean_file'], 'r')
            m = np.load(pfile)
            pfile.close()
        else:
            m = [[[128.0]], [[128.0]], [[128.0]]]

        m = np.mean(np.mean(m, axis=1), axis=1)

        self.mean_pixel_value = np.array([m[0], m[1], m[2]])

        self.pixel_scaling = self.cfgs['pixel_scaling'][
            'test'] if 'pixel_scaling' in self.cfgs.keys() else None

        self.channel_swap = self.cfgs['channel_swap'][
            'test'] if 'channel_swap' in self.cfgs.keys() else None

        self.image_shuffle = self.cfgs['image_shuffle'][
            'test'] if 'image_shuffle' in self.cfgs.keys() else None

    def jsonify(self, results):

        return [[r[0], str(r[1])] for r in results]

    def map_to_synsets(self, results):

        results = {r[0]: r[1] for r in results}

        return [results[c] for c in self.concepts]

    def parse_predictions(self, p):

        sort_idx = np.argsort(-p)

        concepts = [(self.concepts[idx], float(p[idx]), idx)
                    for idx in sort_idx[:self.cfgs['top_k']['test']]]
        #import ipdb; ipdb.set_trace()
        return concepts

    def parse_gndTruth_withFilter(self, ids, p):

        p = np.array(p)
        concepts = np.array(self.concepts)
        filtered_gt = p[ids]
        filtered_concepts = concepts[ids]

        gt_ids = np.where(filtered_gt == 1)[0]

        #sort_idx = np.argsort(-p)

        #import ipdb; ipdb.set_trace()
        return filtered_concepts[gt_ids]

    def parse_gndTruth(self, p):
        #import ipdb; ipdb.set_trace()
        gt = np.array(p)
        concepts = np.array(self.concepts)
        #filtered_gt=p[ids]
        #filtered_concepts=concepts[ids]

        gt_ids = np.where(gt == 1)[0]

        #sort_idx = np.argsort(-p)

        #import ipdb; ipdb.set_trace()
        return concepts[gt_ids]

    def classify_images(self, images):

        confidence = [None]

        if images == []:
            return False, [(), ()], 0.0
        try:

            tstart = time.time()

            (predictions, features) = self.inference(images)
            #import ipdb; ipdb.set_trace()
            predictions = f(predictions, self.beta)[0]
            #import ipdb; ipdb.set_trace()
            #pickle.dump(predictions,open('predictions','wb'))
            #test=f(predictions,self.beta)[0]
            #predictions=numpy_tensor_mean(predictions,self.beta,1)[0]

            #import ipdb; ipdb.set_trace()
            # if len(predictions.shape) == 4:
            #     predictions=predictions[:,:,0,0]
            #import ipdb; ipdb.set_trace()
            if self.label_vectors is not None:
                predictions /= np.linalg.norm(predictions, axis=1)[:,
                                                                   np.newaxis]
                predictions = np.dot(predictions, self.label_vectors)

            if self.confidence_model is not None:
                confidence = [('Confidence', p)
                              for p in self.confidence_model.predict(features)]

            tend = time.time()

        except Exception as err:
            self.io.print_error('Error processing image, {0}'.format(err))
            return False, [(), ()], None, 0.0

        # if not self.raw_predictions:
        #     results = [self.parse_predictions(p)[1] for p in predictions] , True, [self.parse_predictions(p)[0] for p in predictions], confidence, '{0:.4f}'.format((tend - tstart))
        # else:
        #     results = True, predictions, confidence, '{0:.4f}'.format((tend - tstart))
        #results = True, [self.parse_predictions(p) for p in predictions], confidence, '{0:.4f}'.format((tend - tstart))
        results = True, predictions, confidence, '{0:.4f}'.format(
            (tend - tstart))
        return results

    def predict(self, image):

        image = self.normalize_images([image])

        return self.classify_images(image)

    def normalize_images(self, images):

        normalize_images = []

        for image in images:

            image *= 255.0

            if self.cfgs['square_crop']:
                if self.verbose:
                    self.io.print_info(
                        'Yo ! As you like it - Squaring up the image')
                image = self.square_it_up(image)

            try:
                image = cv2.resize(image, (self.im_h, self.im_w))
            except Exception as err:
                self.io.print_error('Could not parse test image {0}'.format(e))
                return False, [], 0.0

            image -= self.mean_pixel_value
            image = image.transpose(2, 0, 1)

            # Channel swap since caffe.io.load_image returns RGB image and training was done with BGR
            image = image[(2, 1, 0), :, :]

            normalize_images.append(image)

        return [np.array(normalize_images)]

    def scale_image(self, image):

        #
        # caffe scales image 0-1 in pixel values we bring it back to 255 as keras likes it that way
        #

        # No more caffe no more scaling down to 0-1 in caffe
        # image *= 255.0

        tstart = time.time()

        if self.cfgs['square_crop']:
            if self.verbose:
                self.io.print_info(
                    'Yo ! As you like it - Squaring up the image')
            image = self.square_it_up(image)

        tend = time.time()

        tstart = time.time()

        try:
            if self.resize_test:
                #Tracer()()
                #print image.size
                image = cv2.resize(image,
                                   (self.im_h, self.im_w)).astype(np.float32)
            else:
                print 'no resize'
                image = image.astype(np.float32)
        except Exception as e:
            self.io.print_error('Could not parse {0}'.format(e))
            return None

        tend = time.time()

        tstart = time.time()

        if self.mean_pixel_value is not None:
            image -= self.mean_pixel_value

        if self.pixel_scaling is not None:
            image /= self.pixel_scaling

        if self.channel_swap is not None:
            image = image[:, :, self.channel_swap]

        # H,W,C to C,H,W
        if self.image_shuffle is not None:
            image = image.transpose(self.image_shuffle)

        tend = time.time()

        return image

    def fetch_images(self, image_file_names):

        images = []
        basenames = []

        tstart = time.time()

        for idx, image_file_name in enumerate(image_file_names):

            image_file_name = image_file_name.replace('/nas/', '/nas2/')

            im_basename = os.path.basename(image_file_name)
            im_basename, _ = os.path.splitext(im_basename)

            if not urlparse.urlparse(image_file_name).scheme == "":

                url_response = urllib.urlopen(image_file_name)

                if url_response.code == 404:
                    print self.io.print_error(
                        '[Testing] URL error code : {1} for {0}'.format(
                            image_file_name, url_response.code))
                    continue

                try:

                    string_buffer = StringIO.StringIO(url_response.read())
                    image = np.asarray(bytearray(string_buffer.read()),
                                       dtype="uint8")

                    image = cv2.imdecode(image, cv2.IMREAD_COLOR)
                    image = image[:, :, (2, 1, 0)]
                    image = image.astype(np.float32)

                except Exception as err:

                    print self.io.print_error(
                        '[Testing] Error with URL {0} {1}'.format(
                            image_file_name, err))
                    continue

            elif os.path.exists(image_file_name):

                try:

                    fid = open(image_file_name, 'r')
                    stream = fid.read()
                    fid.close()

                    image = Image.open(cStringIO.StringIO(stream))
                    image = np.array(image)
                    image = image.astype(np.float32)

                    # image = cv2.imread(image_file_name)
                    # image = image[:, :, (2, 1, 0)]
                    # image = image.astype(np.float32)

                    if image.ndim == 2:
                        image = image[:, :, np.newaxis]
                        image = np.tile(image, (1, 1, 3))
                    elif image.shape[2] == 4:
                        image = image[:, :, :3]

                except Exception as err:

                    print self.io.print_error(
                        '[Testing] Error with image file {0} {1}'.format(
                            image_file_name, err))
                    continue
            else:

                try:

                    image = self.conn.read_image(image_file_name)

                    if image is None:
                        raise self.io.print_error(
                            "[Testing] Image data could not be loaded - %s" %
                            image_file_name)
                        continue

                    image = np.array(image)

                    if image.ndim == 2:
                        image = image[:, :, np.newaxis]
                        image = np.tile(image, (1, 1, 3))
                    elif image.shape[2] == 4:
                        image = image[:, :, :3]

                except Exception as err:

                    print self.io.print_error(
                        '[Testing] Error with S3 Bucket hash {0} {1}'.format(
                            image_file_name, err))
                    continue

            # try : do or do not there is not try
            #orig_image=image.astype('u1')

            image = self.scale_image(image)

            if image is None:
                continue

            if self.verbose:
                self.io.print_info('Processing {0} {1}'.format(
                    image_file_name, image.shape))

            images.append(image)

            basenames.append(im_basename)

        tend = time.time()

        self.io.print_info('Fetching {0} images took {1:.4f} secs'.format(
            len(image_file_names), tend - tstart))

        #return ([np.array(images)], basenames,orig_images)
        return ([np.array(images)], basenames)

    def fetch_gif_frames(self, inGif):

        # Only works for URLs for now
        # write frames to disk and pass filenames to fetch_images

        outFolder = '/tmp'

        frame = Image.open(BytesIO(urllib.urlopen(inGif).read()))
        nframes = 0

        file_names = []

        while frame:
            frame_name = '{0}/{1}-{2}.png'.format(outFolder,
                                                  os.path.basename(inGif),
                                                  nframes)
            frame.save(frame_name, 'png')
            file_names.append(frame_name)
            nframes += 1
            try:
                frame.seek(nframes)
            except EOFError:
                break

        file_names = [file_names[i] for i in range(0, len(file_names), 10)]

        return file_names

    def non_max(self, predictions):

        concepts = {}

        for pred in predictions:
            for p in pred:
                if p[0] in concepts.keys():
                    concepts[p[0]].append(float(p[1]))
                else:
                    concepts[p[0]] = [float(p[1])]

        for key, value in concepts.items():
            concepts[key] = np.max(np.array(value))

        labels = concepts.keys()
        scores = [concepts[l] for l in labels]

        sort_idx = np.argsort(-np.array(scores))

        results = [(labels[idx], str(scores[idx])) for idx in sort_idx]

        return [results]

    def square_it_up(self, image):

        edge_size = np.min(image.shape[:2])
        cy, cx = np.array(image.shape[:2]) // 2

        r_img = image[np.max([0, cy - edge_size //
                              2]):np.min([cy +
                                          edge_size // 2, image.shape[0]]),
                      np.max([0, cx - edge_size //
                              2]):np.min([cx +
                                          edge_size // 2, image.shape[1]]), :]

        return r_img

    def resolve_duplicates(self, concepts):

        seen = set()
        unique = []

        for c in concepts:
            if c[0] in seen:
                logger.debug("Suppressing duplicate {}:{}".format(c[0], c[1]))
                continue
            seen.add(c[0])
            unique.append(c)

        return unique

    def filter_concepts(self, predictions):

        return [p[:self.cfgs['store_top_k']] for p in predictions]

    def suppress_stop_list(self, predictions):

        return [c for c in predictions if c[0] not in self.cfgs['stop_list_']]

    def run_thresholds(self, predictions):

        return self.threshold_concepts(predictions)

    def resolve_antonyms(self, human_predictions):

        conflicting_predictions = []
        human_dict = {d[0]: d[1] for d in human_predictions}

        human_labels = [d[0] for d in human_predictions]
        human_scores = [d[1] for d in human_predictions]

        for c1, c2 in self.cfgs['antonym_list']:

            if not (c1 in human_labels and c2 in human_labels):
                continue
            # if

            s1, s2 = human_dict[c1], human_dict[c2]
            idx = human_labels.index(c2) if s1 > s2 else human_labels.index(c1)

            logger.debug('Suppressing {0}:{1}'.format(human_labels[idx],
                                                      human_scores[idx]))

            del human_labels[idx]
            del human_scores[idx]

        # for

        remove_flag = -1

        for idx, group in enumerate(self.cfgs['count_order_list']):

            _this = np.intersect1d(human_dict.keys(), group)

            if len(_this) > 0:
                remove_flag = idx + 1
                break
                # if

        # for

        if not remove_flag == len(self.cfgs['count_order_list']):

            remove_tags = []

            for g in self.cfgs['count_order_list'][remove_flag:]:
                remove_tags.extend(g)
            # for

            for t in remove_tags:

                if t not in human_labels:
                    continue
                # if

                ridx = human_labels.index(t)

                del human_labels[ridx]
                del human_scores[ridx]

                # for

        # if

        return [(g, s) for g, s in zip(human_labels, human_scores)]

    # def

    def map_concepts(self, concepts):

        mapped_predictions = [(self.mapping[c[0]],
                               c[1]) if c[0] in self.mapping.keys() else c
                              for c in concepts]

        mapped_predictions = self.conditional_mapping(mapped_predictions)

        return mapped_predictions

    # def

    def conditional_mapping(self, predictions):

        if 'conditional_list' in self.cfgs.keys():

            for condition, mapping in self.cfgs['conditional_list']:

                concepts = [p[0] for p in predictions]

                holds = list(set(concepts).intersection(set(condition)))

                if not len(holds) == 0:
                    predictions = [
                        p for p in predictions if not p[0] in mapping
                    ]
                    # if

                    # for

        # if

        return predictions

    # def

    def threshold_concepts(self, predictions):

        if self.thresholds is not None:
            predictions = [
                p for p in predictions if p[1] >= self.thresholds[p[0]]
            ]

        # if

        return predictions
class TheanoTesterCaptions():
    def __init__(self, config_file, verbose=False, raw_predictions=False):

        if not os.path.exists(config_file):
            print 'Error : could not find config file'.format(config_file)
            self.init = False
            return

        self.tester_config_file = config_file
        self.verbose = verbose
        self.raw_predictions = raw_predictions
        self.read_config()

        self.io = EmbeddingIO(self.cfgs['log_dir'], 'testing')

        self.tester_name = self.cfgs['model_name']
        self.model_config_file = self.cfgs['model_config_file']

        self.init = False
        self.thresholds = None

        mapping_keys = [d[0] for d in self.cfgs['mapping_list']]
        mapping_values = [d[1] for d in self.cfgs['mapping_list']]

        self.mapping = dict(zip(mapping_keys, mapping_values))

        if self.tester_name not in model_dict.keys():
            self.io.print_error(
                'Not a valid model type {0} chose among {1}'.format(
                    self.tester_name, model_dict.keys()))
            self.init = False
            return

        if not os.path.exists(self.tester_config_file):
            self.io.print_error('Could not find configuration file {0}'.format(
                self.tester_config_file))
            self.init = False
            return

        self.tester = None
        self.action_items = {'test': self.run, 'eval': self.eval}

    def _read_threshold_file(self):

        if 'threshold_file' in self.cfgs.keys():

            try:

                pfile = open(self.cfgs['threshold_file'], 'r')
                thresholds = json.load(pfile)
                pfile.close()

                self.thresholds = {
                    c: thresholds[c] if c in thresholds.keys() else
                    self.cfgs['global_threshold']
                    for c in self.concepts
                }

            except Exception as err:

                self.io.print_error(
                    'Error parsing threshold file {0},{1}'.format(
                        self.cfgs['threshold_file'], err))

    def read_config(self):

        pfile = open(self.tester_config_file)
        self.cfgs = yaml.load(pfile)
        pfile.close()

    def setup(self):

        self.tester = model_dict[self.tester_name]()
        self.tester.configure(self.model_config_file)

        self.tester.define()

        self.model_type = self.tester.model.get_config()['name']

        self.im_h, self.im_w = self.tester.cfgs[
            'image_height'], self.tester.cfgs['image_width']

        if not self.tester.init:
            self.io.print_error('Error with model definition')
            self.init = False
            return

        self.io.print_info('{0} Model defined from {1}'.format(
            self.tester_name, self.model_config_file))

        self.compile()

        if not self.tester.init:
            self.io.print_error('Error with model compilation')
            self.init = False
            return

        self.io.print_info('{0} Model compiled'.format(self.tester_name))

        self.init = True
        self.load_synset_file()
        self.load_mean_file()
        self._read_threshold_file()
        self.load_confidence_model()
        self.read_label_embedding()

    def compile(self):
        """
            This compile version is to be used for testing only. Since its optimized for predictions
        """

        self.output_nodes = self.cfgs['output_node_name']['test']

        if self.model_type == 'Sequential':
            self.inference = K.function(
                [self.tester.model.get_input(train=False)],
                [self.tester.model.layers[-1].get_output(train=False)])
        elif self.model_type == 'Graph':
            self.inference = K.function(
                [self.tester.model.get_input(train=False)], [
                    self.tester.model.nodes[node].get_output(train=False)
                    for node in self.output_nodes
                ])
        else:
            self.io.print_error(
                'Say whaaaat ?! This model type is not supported : {}'.format(
                    self.model_type))
            sel.init = False

    def read_label_embedding(self):

        self.label_embedding = None
        self.label_vectors = None

        if 'label_embedding_file' in self.cfgs.keys():

            self.label_embedding = self.io.read_npz_file(
                self.cfgs['label_embedding_file'], 'matrix')
            self.label_vectors = self.io.read_npz_file(
                self.cfgs['label_embedding_file'], 'vectors')

            self.io.print_info('Read label embedding file {0}'.format(
                self.cfgs['label_embedding_file']))

    def load_confidence_model(self):

        self.confidence_model = None

        if 'confidence_model' in self.cfgs.keys():
            self.confidence_model = joblib.load(self.cfgs['confidence_model'])

    def run(self):

        self.load_synset_file()

        if not self.init:
            return

        self.test_images = self.io.read_images(self.cfgs['test_file_list'])
        image_batches = [
            self.test_images[i:i + self.cfgs['batch_size']]
            for i in range(0, len(self.test_images), self.cfgs['batch_size'])
        ]

        self.io.print_info('{0} images split into {1} Batches of {2}'.format(
            len(self.test_images), len(image_batches),
            self.cfgs['batch_size']))

        for idx, images in enumerate(image_batches):

            if not self.cfgs['force']:

                flag = self.check_jsons(images)

                if flag:
                    self.io.print_warning('Skipping batch {0} of {1}'.format(
                        idx, len(image_batches)))
                    continue

            pixels, basenames = self.fetch_images(images)
            flag, predictions, confidence, t = self.classify_images(pixels)

            if self.raw_predictions is False:
                getty_like_filter = [
                    self.suppress_stop_list(g) for g in predictions
                ]
                getty_like_safe = [
                    self.run_thresholds(g) for g in getty_like_filter
                ]
                getty_like_pc = [self.map_concepts(g) for g in getty_like_safe]
                getty_like_public = [
                    self.resolve_antonyms(g) for g in getty_like_pc
                ]
                getty_like_unique = [
                    self.resolve_duplicates(g) for g in getty_like_public
                ]
                predictions_pc = getty_like_unique
                save_ext = '.json'
            else:
                predictions_pc = predictions
                save_ext = '.npz'

            if not flag:
                continue

            file_paths = [
                os.path.join(self.cfgs['results_dir'], im + save_ext)
                for im in basenames
            ]

            if not self.raw_predictions:
                to_save = [dict({'external': p}) for p in predictions_pc]
            else:
                to_save = predictions_pc

            assert (len(file_paths) == len(to_save))

            self.io.print_info('Done batch {0} of {1} in {2} secs'.format(
                idx, len(image_batches), t))

            f = map(self.io.save_good_labels, file_paths, to_save)

    def check_jsons(self, images):

        basenames = []

        for image in images:

            im_basename = os.path.basename(image)
            im_basename, _ = os.path.splitext(im_basename)

            basenames.append(im_basename)

        flags = [
            os.path.exists(os.path.join(self.cfgs['results_dir'], b + '.json'))
            for b in basenames
        ]

        return np.all(flags)

    #
    # Which measure to keep
    # Precision/Recall/F1 scores
    #

    def eval(self):

        self.load_synset_file()

        self.test_images = self.io.read_images(self.cfgs['val_file_list'])

        self.predictions = {}
        self.gt = {}

        for idx, image in enumerate(self.test_images):

            if idx % 1000 == 0:
                self.io.print_info('Reading {0}/{1}'.format(
                    idx, len(self.test_images)))

            im_basename = os.path.basename(image)
            im_basename, _ = os.path.splitext(im_basename)

            result_json = os.path.join(self.cfgs['results_dir'],
                                       im_basename + '.json')
            gt_json = os.path.join(self.cfgs['gt_dir'], im_basename + '.json')

            p, s = self.io.read_prediction_json(result_json)
            g = self.io.read_vector(gt_json)

            if p is [] or g is []:
                continue

            self.predictions[im_basename] = zip(p, s)
            self.gt[im_basename] = list(set(g).intersection(self.concepts))

        for t in self.cfgs['thresholds']:
            self.compute_precision_recall(t)

    def compute_precision_recall(self, thresh):

        fps = {}
        tps = {}
        fns = {}
        gt_dict = {}

        for c in self.concepts:
            fps[c], tps[c], fns[c], gt_dict[c] = [], [], [], []

        for key, value in self.predictions.items():

            detections = [v[0] for v in value if v[1] >= thresh]
            gt = self.gt[key]

            for g in gt:
                gt_dict[g].append(key)

            tp = list(set(gt).intersection(detections))
            fp = list(set(detections) - set(gt))
            fn = list(set(gt) - set(detections))

            for t in tp:
                tps[t].append(key)

            for f in fp:
                fps[f].append(key)

            for n in fn:
                fns[n].append(key)

        for c in self.concepts:

            if gt_dict[c] == []:
                self.io.print_info(
                    'Skipping {0}, no samples in ground-truth'.format(c))
                continue

            p = len(tps[c]) / (len(tps[c]) + len(fps[c]) + 0.00000001)
            r = len(tps[c]) / (len(gt_dict[c]) + 0.0)

            f1 = self.compute_f1(p, r)

            self.io.print_info(
                'At {0} : {1} precision {2}, recall {3}, f1-score {4}'.format(
                    c, thresh, p, r, f1))

    def compute_f1(self, p, r):

        return 2 * (p * r) / (p + r + 0.000001)

    def load_synset_file(self):

        pfile = open(self.cfgs['synset_file'], 'r')
        concepts = pfile.readlines()
        pfile.close()

        self.concepts = [p.strip() for p in concepts]

    def load_mean_file(self):

        if not self.cfgs['mean_file'] == 'None':
            pfile = open(self.cfgs['mean_file'], 'r')
            m = np.load(pfile)
            pfile.close()
        else:
            m = [[[128.0]], [[128.0]], [[128.0]]]

        m = np.mean(np.mean(m, axis=1), axis=1)

        self.mean_pixel_value = np.array([m[0], m[1], m[2]])

        self.pixel_scaling = self.cfgs['pixel_scaling'][
            'test'] if 'pixel_scaling' in self.cfgs.keys() else None

        self.channel_swap = self.cfgs['channel_swap'][
            'test'] if 'channel_swap' in self.cfgs.keys() else None

        self.image_shuffle = self.cfgs['image_shuffle'][
            'test'] if 'image_shuffle' in self.cfgs.keys() else None

    def jsonify(self, results):

        return [[r[0], str(r[1])] for r in results]

    def map_to_synsets(self, results):

        results = {r[0]: r[1] for r in results}

        return [results[c] for c in self.concepts]

    def parse_predictions(self, p):

        sort_idx = np.argsort(-p)

        concepts = [(self.concepts[idx], float(p[idx]))
                    for idx in sort_idx[:self.cfgs['top_k']['test']]]

        return concepts

    def classify_images(self, images):

        confidence = [None]

        if images == []:
            return False, [(), ()], 0.0

        try:

            tstart = time.time()

            (predictions, features) = self.inference(images)

            if self.label_vectors is not None:
                predictions /= np.linalg.norm(predictions, axis=1)[:,
                                                                   np.newaxis]
                predictions = np.dot(predictions, self.label_vectors)

            if self.confidence_model is not None:
                confidence = [('Confidence', p)
                              for p in self.confidence_model.predict(features)]

            tend = time.time()

        except Exception as err:
            self.io.print_error('Error processing image, {0}'.format(err))
            return False, [(), ()], None, 0.0

        if not self.raw_predictions:
            results = True, [self.parse_predictions(p) for p in predictions
                             ], confidence, '{0:.4f}'.format((tend - tstart))
        else:
            results = True, predictions, confidence, '{0:.4f}'.format(
                (tend - tstart))

        return results

    def predict(self, image):

        image = self.normalize_images([image])

        return self.classify_images(image)

    def normalize_images(self, images):

        normalize_images = []

        for image in images:

            image *= 255.0

            if self.cfgs['square_crop']:
                if self.verbose:
                    self.io.print_info(
                        'Yo ! As you like it - Squaring up the image')
                image = self.square_it_up(image)

            try:
                image = cv2.resize(image, (self.im_h, self.im_w))
            except Exception as err:
                self.io.print_error('Could not parse test image {0}'.format(e))
                return False, [], 0.0

            image -= self.mean_pixel_value
            image = image.transpose(2, 0, 1)

            # Channel swap since caffe.io.load_image returns RGB image and training was done with BGR
            image = image[(2, 1, 0), :, :]

            normalize_images.append(image)

        return [np.array(normalize_images)]

    def scale_image(self, image):

        #
        # caffe scales image 0-1 in pixel values we bring it back to 255 as keras likes it that way
        #

        # No more caffe no more scaling down to 0-1 in caffe
        # image *= 255.0

        tstart = time.time()

        if self.cfgs['square_crop']:
            if self.verbose:
                self.io.print_info(
                    'Yo ! As you like it - Squaring up the image')
            image = self.square_it_up(image)

        tend = time.time()

        tstart = time.time()

        try:
            image = cv2.resize(image,
                               (self.im_h, self.im_w)).astype(np.float32)
        except Exception as err:
            self.io.print_error('Could not parse {0}'.format(e))
            return None

        tend = time.time()

        tstart = time.time()

        if self.mean_pixel_value is not None:
            image -= self.mean_pixel_value

        if self.pixel_scaling is not None:
            image /= self.pixel_scaling

        if self.channel_swap is not None:
            image = image[:, :, self.channel_swap]

        # H,W,C to C,H,W
        if self.image_shuffle is not None:
            image = image.transpose(self.image_shuffle)

        tend = time.time()

        return image

    def fetch_images(self, image_file_names):

        images = []
        basenames = []

        tstart = time.time()

        for idx, image_file_name in enumerate(image_file_names):

            im_basename = os.path.basename(image_file_name)
            im_basename, _ = os.path.splitext(im_basename)

            if not urlparse.urlparse(image_file_name).scheme == "":

                url_response = urllib.urlopen(image_file_name)

                if url_response.code == 404:
                    print self.io.print_error(
                        '[Testing] URL error code : {1} for {0}'.format(
                            image_file_name, url_response.code))
                    continue

                try:

                    string_buffer = StringIO.StringIO(url_response.read())
                    image = np.asarray(bytearray(string_buffer.read()),
                                       dtype="uint8")

                    image = cv2.imdecode(image, cv2.IMREAD_COLOR)
                    image = image[:, :, (2, 1, 0)]
                    image = image.astype(np.float32)

                except Exception as err:

                    print self.io.print_error(
                        '[Testing] Error with URL {0} {1}'.format(
                            image_file_name, err))
                    continue

            elif os.path.exists(image_file_name):

                try:

                    fid = open(image_file_name, 'r')
                    stream = fid.read()
                    fid.close()

                    image = Image.open(cStringIO.StringIO(stream))
                    image = np.array(image)
                    image = image.astype(np.float32)

                    # image = cv2.imread(image_file_name)
                    # image = image[:, :, (2, 1, 0)]
                    # image = image.astype(np.float32)

                    if image.ndim == 2:
                        image = image[:, :, np.newaxis]
                        image = np.tile(image, (1, 1, 3))
                    elif image.shape[2] == 4:
                        image = image[:, :, :3]

                except Exception as err:

                    print self.io.print_error(
                        '[Testing] Error with image file {0} {1}'.format(
                            image_file_name, err))
                    continue
            else:

                try:

                    image = self.conn.read_image(image_file_name)

                    if image is None:
                        raise self.io.print_error(
                            "[Testing] Image data could not be loaded - %s" %
                            image_file_name)
                        continue

                    image = np.array(image)

                    if image.ndim == 2:
                        image = image[:, :, np.newaxis]
                        image = np.tile(image, (1, 1, 3))
                    elif image.shape[2] == 4:
                        image = image[:, :, :3]

                except Exception as err:

                    print self.io.print_error(
                        '[Testing] Error with S3 Bucket hash {0} {1}'.format(
                            image_file_name, err))
                    continue

            # try : do or do not there is not try

            image = self.scale_image(image)

            if image is None:
                continue

            if self.verbose:
                self.io.print_info('Processing {0} {1}'.format(
                    image_file_name, image.shape))

            images.append(image)

            basenames.append(im_basename)

        tend = time.time()

        self.io.print_info('Fetching {0} images took {1:.4f} secs'.format(
            len(image_file_names), tend - tstart))

        return [np.array(images)], basenames

    def fetch_gif_frames(self, inGif):

        # Only works for URLs for now
        # write frames to disk and pass filenames to fetch_images

        outFolder = '/tmp'

        frame = Image.open(BytesIO(urllib.urlopen(inGif).read()))
        nframes = 0

        file_names = []

        while frame:
            frame_name = '{0}/{1}-{2}.png'.format(outFolder,
                                                  os.path.basename(inGif),
                                                  nframes)
            frame.save(frame_name, 'png')
            file_names.append(frame_name)
            nframes += 1
            try:
                frame.seek(nframes)
            except EOFError:
                break

        file_names = [file_names[i] for i in range(0, len(file_names), 10)]

        return file_names

    def non_max(self, predictions):

        concepts = {}

        for pred in predictions:
            for p in pred:
                if p[0] in concepts.keys():
                    concepts[p[0]].append(float(p[1]))
                else:
                    concepts[p[0]] = [float(p[1])]

        for key, value in concepts.items():
            concepts[key] = np.max(np.array(value))

        labels = concepts.keys()
        scores = [concepts[l] for l in labels]

        sort_idx = np.argsort(-np.array(scores))

        results = [(labels[idx], str(scores[idx])) for idx in sort_idx]

        return [results]

    def square_it_up(self, image):

        edge_size = np.min(image.shape[:2])
        cy, cx = np.array(image.shape[:2]) // 2

        r_img = image[np.max([0, cy - edge_size //
                              2]):np.min([cy +
                                          edge_size // 2, image.shape[0]]),
                      np.max([0, cx - edge_size //
                              2]):np.min([cx +
                                          edge_size // 2, image.shape[1]]), :]

        return r_img

    def resolve_duplicates(self, concepts):

        seen = set()
        unique = []

        for c in concepts:
            if c[0] in seen:
                logger.debug("Suppressing duplicate {}:{}".format(c[0], c[1]))
                continue
            seen.add(c[0])
            unique.append(c)

        return unique

    def filter_concepts(self, predictions):

        return [p[:self.cfgs['store_top_k']] for p in predictions]

    def suppress_stop_list(self, predictions):

        return [c for c in predictions if c[0] not in self.cfgs['stop_list_']]

    def run_thresholds(self, predictions):

        return self.threshold_concepts(predictions)

    def resolve_antonyms(self, human_predictions):

        conflicting_predictions = []
        human_dict = {d[0]: d[1] for d in human_predictions}

        human_labels = [d[0] for d in human_predictions]
        human_scores = [d[1] for d in human_predictions]

        for c1, c2 in self.cfgs['antonym_list']:

            if not (c1 in human_labels and c2 in human_labels):
                continue
            # if

            s1, s2 = human_dict[c1], human_dict[c2]
            idx = human_labels.index(c2) if s1 > s2 else human_labels.index(c1)

            logger.debug('Suppressing {0}:{1}'.format(human_labels[idx],
                                                      human_scores[idx]))

            del human_labels[idx]
            del human_scores[idx]

        # for

        remove_flag = -1

        for idx, group in enumerate(self.cfgs['count_order_list']):

            _this = np.intersect1d(human_dict.keys(), group)

            if len(_this) > 0:
                remove_flag = idx + 1
                break
                # if

        # for

        if not remove_flag == len(self.cfgs['count_order_list']):

            remove_tags = []

            for g in self.cfgs['count_order_list'][remove_flag:]:
                remove_tags.extend(g)
            # for

            for t in remove_tags:

                if t not in human_labels:
                    continue
                # if

                ridx = human_labels.index(t)

                del human_labels[ridx]
                del human_scores[ridx]

                # for

        # if

        return [(g, s) for g, s in zip(human_labels, human_scores)]

    # def

    def map_concepts(self, concepts):

        mapped_predictions = [(self.mapping[c[0]],
                               c[1]) if c[0] in self.mapping.keys() else c
                              for c in concepts]

        mapped_predictions = self.conditional_mapping(mapped_predictions)

        return mapped_predictions

    # def

    def conditional_mapping(self, predictions):

        if 'conditional_list' in self.cfgs.keys():

            for condition, mapping in self.cfgs['conditional_list']:

                concepts = [p[0] for p in predictions]

                holds = list(set(concepts).intersection(set(condition)))

                if not len(holds) == 0:
                    predictions = [
                        p for p in predictions if not p[0] in mapping
                    ]
                    # if

                    # for

        # if

        return predictions

    # def

    def threshold_concepts(self, predictions):

        if self.thresholds is not None:
            predictions = [
                p for p in predictions if p[1] >= self.thresholds[p[0]]
            ]

        # if

        return predictions