diff --git a/answer_classifier_cached_features/eval.py b/answer_classifier_cached_features/eval.py index 72a394b1306d14f7e4b3f89abef3ef585dd165ce..e5b2a4ec2205b80bbe0cabb80aca9dd3ec9ced1f 100644 --- a/answer_classifier_cached_features/eval.py +++ b/answer_classifier_cached_features/eval.py @@ -39,24 +39,25 @@ def create_initializer(graph, sess, model): def create_batch_generator(mode): if mode=='val': - vqa_image_dir = constants.vqa_val_image_dir + vqa_resnet_feat_dir = constants.vqa_val_resnet_feat_dir vqa_anno = constants.vqa_val_anno num_questions = constants.num_val_questions elif mode=='train': - vqa_image_dir = constants.vqa_train_image_dir + vqa_resnet_feat_dir = constants.vqa_train_resnet_feat_dir vqa_anno = constants.vqa_train_anno num_questions = constants.num_train_questions else: print "mode needs to be one of {'train','test','val'}, found " + mode data_mgr = vqa_data.data( - vqa_image_dir, + vqa_resnet_feat_dir, vqa_anno, constants.vocab_json, constants.vqa_answer_vocab_json, constants.image_size, constants.num_region_proposals, - constants.num_negative_answers) + constants.num_negative_answers, + resnet_feat_dim=constants.resnet_feat_dim) index_generator = tftools.data.random( constants.answer_batch_size, @@ -128,28 +129,43 @@ def create_feed_dict_creator(plh, num_neg_answers): class eval_mgr(): - def __init__(self, eval_data_json): + def __init__(self, eval_data_json, results_json): self.eval_data_json= eval_data_json + self.results_json = results_json self.eval_data = dict() self.correct = 0 self.total = 0 + self.results = [] def eval(self, iter, eval_vars_dict, batch): batch_size = len(batch['question_unencoded']) + for j in xrange(batch_size): dict_entry = dict() dict_entry['question'] = batch['question_unencoded'][j] dict_entry['positive_answer'] = { batch['positive_answer_unencoded'][j]: - str(eval_vars_dict['answer_scores'][j][0,0])} + str(eval_vars_dict['answer_score_' + str(j)][0,0])} dict_entry['negative_answers'] = dict() - for i in xrange(len(batch['negative_answers_unencoded'])): + for i in xrange(len(batch['negative_answers_unencoded'][j])): answer = batch['negative_answers_unencoded'][j][i] dict_entry['negative_answers'][answer] = \ - str(eval_vars_dict['answer_scores'][j][0,i+1]) + str(eval_vars_dict['answer_score_' + str(j)][0,i+1]) question_id = batch['question_id'][j] + pred_answer, pred_score = self.get_pred_answer( + [batch['positive_answer_unencoded'][j]] + \ + batch['negative_answers_unencoded'][j], + eval_vars_dict['answer_score_' + str(j)][0,:].tolist() + ) + + result_entry = { + 'question_id': int(question_id), + 'answer': pred_answer + } + self.results.append(result_entry) + self.eval_data[str(question_id)] = dict_entry print dict_entry @@ -164,6 +180,16 @@ class eval_mgr(): if iter%100==0: self.write_data() + def get_pred_answer(self, answers, scores): + pred_answer = '' + pred_score = -1e5 + for answer, score in zip(answers, scores): + if score > pred_score: + pred_score = score + pred_answer = answer + + return pred_answer, pred_score + def is_correct(self, answer_scores): max_id = np.argmax(answer_scores, 1) if max_id[0]==0: @@ -178,6 +204,9 @@ class eval_mgr(): def write_data(self): with open(self.eval_data_json, 'w') as file: ujson.dump(self.eval_data, file, indent=4, sort_keys=True) + + with open(self.results_json, 'w') as file: + ujson.dump(self.results, file, indent=4, sort_keys=True) def eval( @@ -250,12 +279,15 @@ if __name__=='__main__': print 'Creating dict of vars to be evaluated...' vars_to_eval_dict = { 'accuracy': graph.answer_accuracy, - 'answer_scores': graph.answer_inference.answer_score, } + for j in xrange(constants.answer_batch_size): + vars_to_eval_dict['answer_score_'+str(j)] = \ + graph.answer_inference.answer_score[j] print 'Creating evaluation manager...' evaluator = eval_mgr( - constants.answer_eval_data_json) + constants.answer_eval_data_json, + constants.answer_results_json) print 'Start training...' eval( diff --git a/answer_classifier_cached_features/select_best_model.py b/answer_classifier_cached_features/select_best_model.py new file mode 100644 index 0000000000000000000000000000000000000000..e5b2a4ec2205b80bbe0cabb80aca9dd3ec9ced1f --- /dev/null +++ b/answer_classifier_cached_features/select_best_model.py @@ -0,0 +1,305 @@ +# from word2vec.word_vector_management import word_vector_manager +# import object_attribute_classifier.inference as feature_graph +# import region_relevance_network.inference as relevance_graph +# import answer_classifier.inference as answer_graph +from tftools import var_collect, placeholder_management +import tftools.data +import losses +import constants +import tftools.var_collect as var_collect +import data.vqa_cached_features as vqa_data +import answer_classifier_cached_features.train as train + +import numpy as np +import pdb +import ujson +import tensorflow as tf + + +def create_initializer(graph, sess, model): + class initializer(): + def __init__(self): + with graph.tf_graph.as_default(): + model_vars = graph.vars_to_save + model_restorer = tf.train.Saver(model_vars) + model_restorer.restore(sess, model) + not_to_init = model_vars + all_vars = tf.all_variables() + other_vars = [var for var in all_vars + if var not in not_to_init] + var_collect.print_var_list( + other_vars, + 'vars_to_init') + self.init = tf.initialize_variables(other_vars) + + def initialize(self): + sess.run(self.init) + + return initializer() + +def create_batch_generator(mode): + if mode=='val': + vqa_resnet_feat_dir = constants.vqa_val_resnet_feat_dir + vqa_anno = constants.vqa_val_anno + num_questions = constants.num_val_questions + elif mode=='train': + vqa_resnet_feat_dir = constants.vqa_train_resnet_feat_dir + vqa_anno = constants.vqa_train_anno + num_questions = constants.num_train_questions + else: + print "mode needs to be one of {'train','test','val'}, found " + mode + + data_mgr = vqa_data.data( + vqa_resnet_feat_dir, + vqa_anno, + constants.vocab_json, + constants.vqa_answer_vocab_json, + constants.image_size, + constants.num_region_proposals, + constants.num_negative_answers, + resnet_feat_dim=constants.resnet_feat_dim) + + index_generator = tftools.data.random( + constants.answer_batch_size, + num_questions, + 1, + 0) + + batch_generator = tftools.data.async_batch_generator( + data_mgr, + index_generator, + constants.answer_queue_size) + + return batch_generator + + +def create_feed_dict_creator(plh, num_neg_answers): + def feed_dict_creator(batch): + vqa_batch = batch + batch_size = len(vqa_batch['question']) + # Create vqa inputs + inputs = { + 'region_feats': np.concatenate(vqa_batch['region_feats'], axis=0), + 'positive_answer': vqa_batch['positive_answer'], + } + for i in xrange(4): + bin_name = 'bin_' + str(i) + inputs[bin_name] = [ + vqa_batch['question'][j][bin_name] for j in xrange(batch_size)] + + for i in xrange(num_neg_answers): + answer_name = 'negative_answer_' + str(i) + inputs[answer_name] = [ + vqa_batch['negative_answers'][j][i] for j in xrange(batch_size)] + + inputs['positive_nouns'] = [ + a + b for a, b in zip( + vqa_batch['question_nouns'], + vqa_batch['positive_answer_nouns'])] + + inputs['positive_adjectives'] = [ + a + b for a, b in zip( + vqa_batch['question_adjectives'], + vqa_batch['positive_answer_adjectives'])] + + for i in xrange(num_neg_answers): + name = 'negative_nouns_' + str(i) + list_ith_negative_answer_nouns = [ + vqa_batch['negative_answers_nouns'][j][i] + for j in xrange(batch_size)] + inputs[name] = [ + a + b for a, b in zip( + vqa_batch['question_nouns'], + list_ith_negative_answer_nouns)] + + name = 'negative_adjectives_' + str(i) + list_ith_negative_answer_adjectives = [ + vqa_batch['negative_answers_adjectives'][j][i] + for j in xrange(batch_size)] + inputs[name] = [ + a + b for a, b in zip( + vqa_batch['question_adjectives'], + list_ith_negative_answer_adjectives)] + + inputs['keep_prob'] = 1.0 + + return plh.get_feed_dict(inputs) + + return feed_dict_creator + + +class eval_mgr(): + def __init__(self, eval_data_json, results_json): + self.eval_data_json= eval_data_json + self.results_json = results_json + self.eval_data = dict() + self.correct = 0 + self.total = 0 + self.results = [] + + def eval(self, iter, eval_vars_dict, batch): + batch_size = len(batch['question_unencoded']) + + for j in xrange(batch_size): + dict_entry = dict() + dict_entry['question'] = batch['question_unencoded'][j] + dict_entry['positive_answer'] = { + batch['positive_answer_unencoded'][j]: + str(eval_vars_dict['answer_score_' + str(j)][0,0])} + + dict_entry['negative_answers'] = dict() + for i in xrange(len(batch['negative_answers_unencoded'][j])): + answer = batch['negative_answers_unencoded'][j][i] + dict_entry['negative_answers'][answer] = \ + str(eval_vars_dict['answer_score_' + str(j)][0,i+1]) + + question_id = batch['question_id'][j] + pred_answer, pred_score = self.get_pred_answer( + [batch['positive_answer_unencoded'][j]] + \ + batch['negative_answers_unencoded'][j], + eval_vars_dict['answer_score_' + str(j)][0,:].tolist() + ) + + result_entry = { + 'question_id': int(question_id), + 'answer': pred_answer + } + self.results.append(result_entry) + + self.eval_data[str(question_id)] = dict_entry + + print dict_entry + + self.total += batch_size + + self.correct += eval_vars_dict['accuracy']*batch_size + + self.print_accuracy() + + + if iter%100==0: + self.write_data() + + def get_pred_answer(self, answers, scores): + pred_answer = '' + pred_score = -1e5 + for answer, score in zip(answers, scores): + if score > pred_score: + pred_score = score + pred_answer = answer + + return pred_answer, pred_score + + def is_correct(self, answer_scores): + max_id = np.argmax(answer_scores, 1) + if max_id[0]==0: + return True + + def print_accuracy(self): + print 'Total: {} Correct: {} Accuracy: {}'.format( + self.total, + self.correct, + self.correct/float(self.total)) + + def write_data(self): + with open(self.eval_data_json, 'w') as file: + ujson.dump(self.eval_data, file, indent=4, sort_keys=True) + + with open(self.results_json, 'w') as file: + ujson.dump(self.results, file, indent=4, sort_keys=True) + + +def eval( + batch_generator, + sess, + initializer, + vars_to_eval_dict, + feed_dict_creator, + evaluator): + + vars_to_eval_names = [] + vars_to_eval = [] + for var_name, var in vars_to_eval_dict.items(): + vars_to_eval_names += [var_name] + vars_to_eval += [var] + + with sess.as_default(): + initializer.initialize() + + iter = 0 + for batch in batch_generator: + print '---' + print 'Iter: {}'.format(iter) + feed_dict = feed_dict_creator(batch) + eval_vars = sess.run( + vars_to_eval, + feed_dict = feed_dict) + eval_vars_dict = { + var_name: eval_var for var_name, eval_var in + zip(vars_to_eval_names, eval_vars)} + evaluator.eval(iter, eval_vars_dict, batch) + iter+=1 + + evaluator.write_data() + + +if __name__=='__main__': + print 'Creating batch generator...' + batch_generator = create_batch_generator(constants.answer_eval_on) + + print 'Creating computation graph...' + graph = train.graph_creator( + constants.tb_log_dir, + constants.answer_batch_size, + constants.image_size, + constants.num_negative_answers, + constants.answer_embedding_dim, + constants.answer_regularization_coeff, + constants.answer_batch_size*constants.num_region_proposals, + 0, + 0, + 0, + resnet_feat_dim=constants.resnet_feat_dim, + training=False) + + print 'Starting a session...' + sess = tf.Session(graph=graph.tf_graph) + + print 'Creating initializer...' + initializer = create_initializer( + graph, + sess, + constants.answer_model_to_eval) + + print 'Creating feed dict creator...' + feed_dict_creator = create_feed_dict_creator( + graph.plh, + constants.num_negative_answers) + + print 'Creating dict of vars to be evaluated...' + vars_to_eval_dict = { + 'accuracy': graph.answer_accuracy, + } + for j in xrange(constants.answer_batch_size): + vars_to_eval_dict['answer_score_'+str(j)] = \ + graph.answer_inference.answer_score[j] + + print 'Creating evaluation manager...' + evaluator = eval_mgr( + constants.answer_eval_data_json, + constants.answer_results_json) + + print 'Start training...' + eval( + batch_generator, + sess, + initializer, + vars_to_eval_dict, + feed_dict_creator, + evaluator) + + + + + + diff --git a/constants.py b/constants.py index 47443cc308e07a806c7bcf89c8e13139c765d6e8..7c96051665f4d068c5edd14526cb3e872030a71a 100644 --- a/constants.py +++ b/constants.py @@ -7,3 +7,4 @@ elif hostname=='vision-gpu-2': from constants_vision_gpu_2 import * elif hostname=='crunchy': from constants_crunchy import * + diff --git a/data/vqa_cached_features.py b/data/vqa_cached_features.py index 9fdf937089987d277f3dcddffe00ae497a49b556..913654e8a2ac981bfeab64f2a1a73a1cfe8cad72 100644 --- a/data/vqa_cached_features.py +++ b/data/vqa_cached_features.py @@ -32,6 +32,10 @@ class data(): resnet_feat_dim=2048, mean_image_filename=None): self.feat_dir = feat_dir + # data_split = re.split( + # '_', + # os.path.split(self.feat_dir)[1])[0] + # pdb.set_trace() self.h = image_size[0] self.w = image_size[1] self.c = channels @@ -124,9 +128,13 @@ class data(): def get_region_feats(self, sample): question_id = self.sample_to_question_dict[sample] image_id = self.anno[str(question_id)]['image_id'] + data_split = re.split( + '_', + os.path.split(self.feat_dir)[1])[0] + feat_path = os.path.join( self.feat_dir, - 'COCO_train2014_' + str(image_id).zfill(12) + '.npy') + 'COCO_' + data_split + '_' + str(image_id).zfill(12) + '.npy') return np.load(feat_path) def get_single_image(self, sample, region_number, batch_list, worker_id): diff --git a/tftools/placeholder_management.py b/tftools/placeholder_management.py index 2f7c13f77fcf2f93cdacd0fc96795b45843ee07c..45958deb02c1a2bf05815e0fcfd10f1e94956d68 100644 --- a/tftools/placeholder_management.py +++ b/tftools/placeholder_management.py @@ -223,12 +223,13 @@ class PlaceholderManager(): if __name__ == '__main__': + sess = tf.InteractiveSession() plh = PlaceholderManager() plh.add_list_placeholder( 'list_of_ints', tf.int32, 3, - [1,2], + [2], ) inputs = { @@ -238,7 +239,12 @@ if __name__ == '__main__': [3,4]] } + list_of_ints = plh['list_of_ints'] + z = list_of_ints[0] + list_of_ints[1] feed_dict = plh.get_feed_dict(inputs) + print z.eval(feed_dict) print plh.feed_dict_debug_string(feed_dict) + + pdb.set_trace()