Spaces:
Runtime error
Runtime error
| # -*- coding: utf-8 -*- | |
| """ Official evaluation script for v1.0 of the TriviaQA dataset. | |
| Extended from the evaluation script for v1.1 of the SQuAD dataset. """ | |
| from __future__ import print_function | |
| from collections import Counter | |
| import string | |
| import re | |
| import sys | |
| import argparse | |
| from . import file_utils | |
| from . import dataset_utils | |
| def normalize_answer(s): | |
| """Lower text and remove punctuation, articles and extra whitespace.""" | |
| def remove_articles(text): | |
| return re.sub(r'\b(a|an|the)\b', ' ', text) | |
| def white_space_fix(text): | |
| return ' '.join(text.split()) | |
| def handle_punc(text): | |
| exclude = set(string.punctuation + "".join([u"‘", u"’", u"´", u"`"])) | |
| return ''.join(ch if ch not in exclude else ' ' for ch in text) | |
| def lower(text): | |
| return text.lower() | |
| def replace_underscore(text): | |
| return text.replace('_', ' ') | |
| return white_space_fix(remove_articles(handle_punc(lower(replace_underscore(s))))).strip() | |
| def f1_score(prediction, ground_truth): | |
| prediction_tokens = normalize_answer(prediction).split() | |
| ground_truth_tokens = normalize_answer(ground_truth).split() | |
| common = Counter(prediction_tokens) & Counter(ground_truth_tokens) | |
| num_same = sum(common.values()) | |
| if num_same == 0: | |
| return 0 | |
| precision = 1.0 * num_same / len(prediction_tokens) | |
| recall = 1.0 * num_same / len(ground_truth_tokens) | |
| f1 = (2 * precision * recall) / (precision + recall) | |
| return f1 | |
| def exact_match_score(prediction, ground_truth): | |
| return int(normalize_answer(prediction) == normalize_answer(ground_truth)) | |
| def metric_max_over_ground_truths(metric_fn, prediction, ground_truths): | |
| scores_for_ground_truths = [] | |
| for ground_truth in ground_truths: | |
| score = metric_fn(prediction, ground_truth) | |
| scores_for_ground_truths.append(score) | |
| return max(scores_for_ground_truths) | |
| def is_exact_match(answer_object, prediction): | |
| ground_truths = get_ground_truths(answer_object) | |
| for ground_truth in ground_truths: | |
| if exact_match_score(prediction, ground_truth): | |
| return True | |
| return False | |
| def has_exact_match(ground_truths, candidates): | |
| for ground_truth in ground_truths: | |
| if ground_truth in candidates: | |
| return True | |
| return False | |
| def get_ground_truths(answer): | |
| return answer['NormalizedAliases'] + [normalize_answer(ans) for ans in answer.get('HumanAnswers', [])] | |
| def get_oracle_score(ground_truth, predicted_answers, qid_list=None, mute=False): | |
| exact_match = common = 0 | |
| if qid_list is None: | |
| qid_list = ground_truth.keys() | |
| for qid in qid_list: | |
| if qid not in predicted_answers: | |
| if not mute: | |
| message = 'Irrelavant question {} will receive score 0.'.format(qid) | |
| print(message, file=sys.stderr) | |
| continue | |
| common += 1 | |
| prediction = normalize_answer(predicted_answers[qid]) | |
| ground_truths = get_ground_truths(ground_truth[qid]) | |
| em_for_this_question = has_exact_match(ground_truths, prediction) | |
| exact_match += int(em_for_this_question) | |
| exact_match = 100.0 * exact_match / len(qid_list) | |
| return {'oracle_exact_match': exact_match, 'common': common, 'denominator': len(qid_list), | |
| 'pred_len': len(predicted_answers), 'gold_len': len(ground_truth)} | |
| def evaluate_triviaqa(ground_truth, predicted_answers, qid_list=None, mute=False): | |
| f1 = exact_match = common = 0 | |
| if qid_list is None: | |
| qid_list = ground_truth.keys() | |
| for qid in qid_list: | |
| if qid not in predicted_answers: | |
| if not mute: | |
| message = 'Missed question {} will receive score 0.'.format(qid) | |
| print(message, file=sys.stderr) | |
| continue | |
| if qid not in ground_truth: | |
| if not mute: | |
| message = 'Irrelavant question {} will receive score 0.'.format(qid) | |
| print(message, file=sys.stderr) | |
| continue | |
| common += 1 | |
| prediction = predicted_answers[qid] | |
| ground_truths = get_ground_truths(ground_truth[qid]) | |
| em_for_this_question = metric_max_over_ground_truths( | |
| exact_match_score, prediction, ground_truths) | |
| if em_for_this_question == 0 and not mute: | |
| print("em=0:", prediction, ground_truths) | |
| exact_match += em_for_this_question | |
| f1_for_this_question = metric_max_over_ground_truths( | |
| f1_score, prediction, ground_truths) | |
| f1 += f1_for_this_question | |
| exact_match = 100.0 * exact_match / len(qid_list) | |
| f1 = 100.0 * f1 / len(qid_list) | |
| return {'exact_match': exact_match, 'f1': f1, 'common': common, 'denominator': len(qid_list), | |
| 'pred_len': len(predicted_answers), 'gold_len': len(ground_truth)} | |
| def get_args(): | |
| parser = argparse.ArgumentParser( | |
| description='Evaluation for TriviaQA {}'.format(expected_version)) | |
| parser.add_argument('--dataset_file', help='Dataset file') | |
| parser.add_argument('--prediction_file', help='Prediction File') | |
| args = parser.parse_args() | |
| return args | |
| if __name__ == '__main__': | |
| expected_version = 1.0 | |
| args = get_args() | |
| dataset_json = dataset_utils.read_triviaqa_data(args.dataset_file) | |
| if dataset_json['Version'] != expected_version: | |
| print('Evaluation expects v-{} , but got dataset with v-{}'.format(expected_version, dataset_json['Version']), | |
| file=sys.stderr) | |
| key_to_ground_truth = dataset_utils.get_key_to_ground_truth(dataset_json) | |
| predictions = file_utils.read_json(args.prediction_file) | |
| eval_dict = evaluate_triviaqa(key_to_ground_truth, predictions) | |
| print(eval_dict) | |