| | import argparse |
| | import json |
| | import os |
| | import re |
| | import random |
| |
|
| |
|
| | def get_args(): |
| | parser = argparse.ArgumentParser() |
| | parser.add_argument('--base-dir', type=str) |
| | parser.add_argument('--result-file', type=str) |
| | parser.add_argument('--output-file', type=str) |
| | parser.add_argument('--output-result', type=str) |
| | parser.add_argument('--split', type=str, default='test') |
| | parser.add_argument('--options', type=list, default=["A", "B", "C", "D", "E"]) |
| | return parser.parse_args() |
| |
|
| |
|
| | def convert_caps(results): |
| | fakecaps = [] |
| | for result in results: |
| | image_id = result['question_id'] |
| | caption = result['text'] |
| | fakecaps.append({"image_id": int(image_id), "caption": caption}) |
| | return fakecaps |
| |
|
| |
|
| | def get_pred_idx(prediction, choices, options): |
| | """ |
| | Get the index (e.g. 2) from the prediction (e.g. 'C') |
| | """ |
| | if prediction in options[:len(choices)]: |
| | return options.index(prediction) |
| | else: |
| | return -1 |
| | return random.choice(range(len(choices))) |
| |
|
| |
|
| | if __name__ == "__main__": |
| | args = get_args() |
| |
|
| | base_dir = args.base_dir |
| | split_indices = json.load(open(os.path.join(base_dir, "pid_splits.json")))[args.split] |
| | problems = json.load(open(os.path.join(base_dir, "problems.json"))) |
| | predictions = [json.loads(line) for line in open(args.result_file)] |
| | predictions = {pred['question_id']: pred for pred in predictions} |
| | split_problems = {idx: problems[idx] for idx in split_indices} |
| |
|
| | results = {'correct': [], 'incorrect': []} |
| | sqa_results = {} |
| | sqa_results['acc'] = None |
| | sqa_results['correct'] = None |
| | sqa_results['count'] = None |
| | sqa_results['results'] = {} |
| | sqa_results['outputs'] = {} |
| |
|
| | for prob_id, prob in split_problems.items(): |
| | if prob_id not in predictions: |
| | pred = {'text': 'FAILED', 'prompt': 'Unknown'} |
| | pred_text = 'FAILED' |
| | else: |
| | pred = predictions[prob_id] |
| | pred_text = pred['text'] |
| |
|
| | if pred_text in args.options: |
| | answer = pred_text |
| | elif len(pred_text) >= 3 and pred_text[0] in args.options and pred_text[1:3] == ". ": |
| | answer = pred_text[0] |
| | else: |
| | pattern = re.compile(r'The answer is ([A-Z]).') |
| | res = pattern.findall(pred_text) |
| | if len(res) == 1: |
| | answer = res[0] |
| | else: |
| | answer = "FAILED" |
| |
|
| | pred_idx = get_pred_idx(answer, prob['choices'], args.options) |
| |
|
| | analysis = { |
| | 'question_id': prob_id, |
| | 'parsed_ans': answer, |
| | 'ground_truth': args.options[prob['answer']], |
| | 'question': pred['prompt'], |
| | 'pred': pred_text, |
| | 'is_multimodal': '<image>' in pred['prompt'], |
| | } |
| |
|
| | sqa_results['results'][prob_id] = get_pred_idx(answer, prob['choices'], args.options) |
| | sqa_results['outputs'][prob_id] = pred_text |
| |
|
| | if pred_idx == prob['answer']: |
| | results['correct'].append(analysis) |
| | else: |
| | results['incorrect'].append(analysis) |
| |
|
| | correct = len(results['correct']) |
| | total = len(results['correct']) + len(results['incorrect']) |
| |
|
| | |
| | multimodal_correct = len([x for x in results['correct'] if x['is_multimodal']]) |
| | multimodal_incorrect = len([x for x in results['incorrect'] if x['is_multimodal']]) |
| | multimodal_total = multimodal_correct + multimodal_incorrect |
| | |
| |
|
| | print(f'Total: {total}, Correct: {correct}, Accuracy: {correct / total * 100:.2f}%, IMG-Accuracy: {multimodal_correct / multimodal_total * 100:.2f}%') |
| |
|
| | sqa_results['acc'] = correct / total * 100 |
| | sqa_results['correct'] = correct |
| | sqa_results['count'] = total |
| |
|
| | with open(args.output_file, 'w') as f: |
| | json.dump(results, f, indent=2) |
| | with open(args.output_result, 'w') as f: |
| | json.dump(sqa_results, f, indent=2) |
| |
|