-
Notifications
You must be signed in to change notification settings - Fork 0
/
eval_alignment.py
96 lines (78 loc) · 2.59 KB
/
eval_alignment.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from __future__ import division
import sys, re, json
from collections import defaultdict
"""
Evaluate a set of test alignments versus the gold set.
"""
class ParseError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
class FScore:
"Compute F1-Score based on gold set and test set."
def __init__(self):
self.gold = 0
self.test = 0
self.correct = 0
def increment(self, gold_set, test_set):
"Add examples from sets."
self.gold += len(gold_set)
self.test += len(test_set)
self.correct += len(gold_set & test_set)
def fscore(self):
pr = self.precision() + self.recall()
if pr == 0: return 0.0
return (2 * self.precision() * self.recall()) / pr
def precision(self):
if self.test == 0: return 0.0
return self.correct / self.test
def recall(self):
if self.gold == 0: return 0.0
return self.correct / self.gold
@staticmethod
def output_header():
"Output a scoring header."
print "%10s %10s %10s %10s %10s"%(
"Type", "Total", "Precision", "Recall", "F1-Score")
print "==============================================================="
def output_row(self, name):
"Output a scoring row."
print "%10s %4d %0.3f %0.3f %0.3f"%(
name, self.gold, self.precision(), self.recall(), self.fscore())
class CorpusAlignment:
"Read in the alignment."
def __init__(self, handle):
self.all_align = set()
self.sents_align = {}
for l in handle:
t = l.strip().split()
if len(t) != 3:
raise ParseError("Alignment must have three columns. %s"%l)
try:
sent = int(t[0])
align = (int(t[1]), int(t[2]))
self.all_align.add((sent, align))
except:
raise ParseError("Alignment line must be integers. %s"%l)
@staticmethod
def compute_fscore(align1, align2):
fscore = FScore()
fscore.increment(align1.all_align, align2.all_align)
return fscore
def main(gold_alignment, test_alignment):
align1 = CorpusAlignment(gold_alignment)
align2 = CorpusAlignment(test_alignment)
fscore = CorpusAlignment.compute_fscore(align1, align2)
FScore.output_header()
fscore.output_row("total")
if __name__ == "__main__":
if len(sys.argv) != 3:
print >>sys.stderr, """
Usage: python eval_alignment.py [key_file] [output_file]
Evalute the accuracy of a output trees compared to a key file.\n"""
sys.exit(1)
if sys.argv[1][-4:] != ".key":
print >>sys.stderr, "First argument should end in '.key'."
sys.exit(1)
main(open(sys.argv[1]), open(sys.argv[2]))