Update to remove faulty gold parses. Seems Done now :)
authorKevin Brubeck Unhammer <pixiemotion@gmail.com>
Sat, 27 Sep 2008 08:12:18 +0000 (27 10:12 +0200)
committerKevin Brubeck Unhammer <pixiemotion@gmail.com>
Sat, 27 Sep 2008 08:12:18 +0000 (27 10:12 +0200)
report/report.pdf
report/report.tex
src/main.py
src/wsjdep.py

index 6d37c40..5d07133 100644 (file)
Binary files a/report/report.pdf and b/report/report.pdf differ
index d3b94ac..d630da1 100644 (file)
@@ -1,4 +1,4 @@
-% merged Kevin's & Emily's reports 2008-09-21 Sun 10:39 with Emerge
+% merged Kevin's & Emily's reports 2008-09-21 Sun 19:04 with Emerge
 
 \documentclass[11pt,a4paper]{article}
 \usepackage[utf8]{inputenc}
@@ -534,44 +534,39 @@ next section discusses the effect of these.
 \subsection{Results}
 We compared the results of the implementation with a dependency parsed
 version of the WSJ-10 corpus (converted from the manually annotated
-version). Since single word sentences were not POS-tagged there, these
-were skipped. Also, the dependency parsed WSJ-10 did not have ROOT
-nodes; so we calculated precision and recall both without counting our
-ROOT links, and with counting ROOT links, by adding these to the gold
-parses where possible\footnote{221 parses in the dependency parsed
-  WSJ-10 had several tokens appearing as heads without appearing as
-  dependents in the same parse, here we skipped the parses when
-  calculating with ROOT links.}.
+version using a Perl script by Valentin Jijkoun). Since single word
+sentences were not POS-tagged there, these were skipped. Also, the
+dependency parsed WSJ-10 did not have ROOT nodes; so we calculated
+precision and recall both without counting our ROOT links, and with
+counting ROOT links, by adding these to the gold parses where
+possible\footnote{221 parses in the dependency parsed WSJ-10 had
+  several tokens appearing as heads without appearing as dependents in
+  the same parse, here we skipped the parses when calculating with
+  ROOT links. Our gold standard also sometimes (for 1249 sentences)
+  had one dependent with two heads, these were skipped from
+  evaluation. We have not yet had time to run evaluation of undirected
+  dependencies.}.
 
 \begin{table*}[hb]
   \centering
   \begin{tabular}{l|ccc}
     Model                          & P             & R              & F1          \\
     \hline 
-    LBRANCH/RHEAD                  & 25.6          & 32.6           & 28.7        \\
-    RANDOM                         & 31.0          & 39.4           & 34.7        \\ 
-    RBRANCH/LHEAD                  & 55.1          & 70.0           & 61.7        \\
-    K\&M's DMV                     & 46.6          & 59.2           & 52.1        \\
+    LBRANCH/RHEAD                  &               &                & 33.6        \\
+    RANDOM                         &               &                & 30.1        \\ 
+    RBRANCH/LHEAD                  &               &                & 24.0        \\
+    K\&M's DMV                     &               &                & 43.2        \\
     Our DMV:                                                                      \\
     Uniform initial distribution   & 21.0 (18.7)   & 20.1 (18.1)    & 20.5 (18.4) \\
-    $C_A=0; C_S=1;C_N=0.1;C_M=1$    & 23.7 (23.7)   & 24.8 (24.5)    & 24.2 (24.1) \\ 
-    $C_A=0; C_S=1;C_N=0.1;C_M=10$   & 26.7 (31.6)   & 25.5 (30.5)    & 26.1 (31.0) \\ 
+    $C_A=0; C_S=1;C_N=0.1;C_M=1$    & 24.8 (24.5)   & 23.7 (23.7)    & 24.2 (24.1) \\ % local screen
+    $C_A=0; C_S=1;C_N=0.1;C_M=10$   & 26.7 (31.6)   & 25.5 (30.5)    & 26.1 (31.0) \\ % uib screen
 %    $C_A=10;C_S=1;C_N=0.1;C_M=10$   & 25.6 (30.6)    & 24.5 (29.6)   & 25.0 (30.1) \\
-    $C_A=10;C_S=1;C_N=3  ;C_M=10$   & 26.0 (31.0)   & 24.9 (30.0)    & 25.5 (30.5) \\
-    $C_A=15;C_S=3;C_N=1  ;C_M=20$   & 26.7 (31.7)   & 25.6 (30.6)    & 26.2 (31.2) \\ 
+    $C_A=10;C_S=1;C_N=3  ;C_M=10$   &               &                & 26.3 (31.4) \\ 
+    $C_A=15;C_S=3;C_N=1  ;C_M=20$   &               &                & 27.2 (32.2) \\
   \end{tabular}
   \caption{DMV results on the WSJ-10 for various initialization values (numbers in parentheses are when counting added ROOT links)}
   \label{tab:dmv-wsj}
 \end{table*}
-% trying locally: ?
-% HARMONIC_C: 115.854497176, STOP_C: 1.47684590293, NSTOP_C:
-% 4.27464793921, FSTOP_MIN: 6.9710245489
-% P:  11627/45444 = 0.255853357979 | P_r:  15710/51712 = 0.303797957921
-% R:  11627/47419 = 0.245197072903 | R_r:  15710/53466 = 0.29383159391
-% F1:               0.250411897096 | F1_r:               0.298731673924 
-% 
-% trying remotely: uniform distribution
-% todo: fix results when done
 
 We tried various values for the initialization constants; but it was
 hard to find any clear pattern for what worked best. 
@@ -596,6 +591,27 @@ not clear whether their DMV-experiment was run using automatically
 induced word classes \citep[Sch├╝tze, 1995, in][p.~8]{km-dmv} or on the
 tagset used to manually annotate the WSJ-10.
 
+% underproposed =     # $C_A=10;C_S=1;C_N=3  ;C_M=10$
+% {(('NN', 1), ('DT', 0)): 347,
+%  (('NN', 2), ('DT', 0)): 148,
+%  (('NN', 3), ('DT', 2)): 136,
+%  (('NN', 4), ('DT', 3)): 144,
+%  (('NN', 5), ('DT', 4)): 128,
+%  (('NN', 6), ('DT', 5)): 124,
+%  (('NNP', 1), ('NNP', 0)): 358,
+%  (('NNP', 2), ('NNP', 0)): 125,
+%  (('NNP', 2), ('NNP', 1)): 174,
+%  (('NNS', 1), ('JJ', 0)): 124,
+%  (('ROOT', -1), ('NN', 0)): 100,
+%  (('ROOT', -1), ('NN', 1)): 106,
+%  (('ROOT', -1), ('NNP', 1)): 140,
+%  (('ROOT', -1), ('NNP', 2)): 104,
+%  (('VBD', 2), ('NN', 1)): 145,
+%  (('VBP', 2), ('NNS', 1)): 111,
+%  (('VBZ', 2), ('NN', 1)): 152,
+%  (('VBZ', 2), ('NNP', 1)): 107,
+%  (('VBZ', 3), ('NN', 2)): 109, }
+
 In the stochastic grammars given by the model after EM, the POS class
 $VBD$ (past tense verb) had the highest probability of being attached
 to by ROOT, followed by $VBZ$ (3sg present) and $VBP$ (non-3sg
index 7b90b7d..a4384ba 100644 (file)
@@ -16,11 +16,11 @@ def initialize_loc_h(tagonlys):
 #     loc_h_harmonic.HARMONIC_C = 380.111684914
 #     loc_h_harmonic.FSTOP_MIN = 13.5744632704
 #     loc_h_harmonic.FNONSTOP_MIN = 34.8939452454
-    loc_h_harmonic.HARMONIC_C = 0.0 #120.0 * random.random() # 509.63
-    loc_h_harmonic.STOP_C = 1.0 #3.0 * random.random() 
-    loc_h_harmonic.NSTOP_C = 0.1 #5.0 * random.random() # 0.1
-    loc_h_harmonic.FSTOP_MIN = 1.0 #20.0 * random.random() # 13.08 
-
+    loc_h_harmonic.HARMONIC_C =  0.0 #120.0 * random.random() # 509.63
+    loc_h_harmonic.STOP_C =      1.0 #3.0 * random.random() 
+    loc_h_harmonic.NSTOP_C =     0.1 #5.0 * random.random() # 0.1
+    loc_h_harmonic.FSTOP_MIN =  10.0 #20.0 * random.random() # 13.08 
+#   $C_A=0; C_S=1;C_N=0.1;C_M=10$
     loc_h_harmonic.RIGHT_FIRST = 1.0
     loc_h_harmonic.OLD_STOP_CALC = False
     print '''
@@ -53,14 +53,14 @@ def test_likelihood(reestimate, initialize, inner_sent,
         sumlog,msg = corpus_likelihood(g, tagonlys)
         print msg
         if EVAL:
-            E = evaluate(g, tags_and_parses)
-            print E
+            g.E = evaluate(g, tags_and_parses)
+            print g.E
         for i in range(iterations):
             g = reestimate(g, tagonlys)
             print "reestimation number %d done\n"%i
             if EVAL:
-                E = evaluate(g, tags_and_parses)
-                print E
+                g.E = evaluate(g, tags_and_parses)
+                print g.E
             prev_sumlog = sumlog
             sumlog,msg = corpus_likelihood(g, tagonlys)
             if sumlog < prev_sumlog:
@@ -70,14 +70,8 @@ def test_likelihood(reestimate, initialize, inner_sent,
             from pickle import dump # let us say g = pickle.load(open('..','rb'))
             filehandler = open('current_grammar.obj','w')
             dump(g, filehandler)
-            
-        if EVAL:
-            import pprint
-            print "underproposed:"
-            pprint.pprint(E.underproposed)
-            print "overproposed:"
-            pprint.pprint(E.overproposed)
-        
+            filehandler.close()
+                    
         return g
 
     def corpus_likelihood(g, tagsonly):
@@ -95,16 +89,20 @@ def test_likelihood(reestimate, initialize, inner_sent,
     reader = WSJDepCorpusReader(None)
     tagonlys = reader.tagonly_sents()[corpus_offset:corpus_offset+corpus_size]
     tags_and_parses = reader.tagged_and_parsed_sents()[corpus_offset:corpus_offset+corpus_size]
-
-#     from loc_h_dmv import testcorpus
-#     tagonlys = testcorpus
     
     print "\ninitializing %d sentences..." % corpus_size,
     g = initialize(tagonlys)
     print "initialized"
     
     g = run_IO(g, iterations, tagonlys, tags_and_parses) # make iterations argument, todo
-    
+
+    if EVAL:
+        import pprint
+        print "underproposed:"
+        pprint.pprint(g.E.underproposed)
+        print "overproposed:"
+        pprint.pprint(g.E.overproposed)
+
     return g
 
 
@@ -117,6 +115,7 @@ class Evaluation():
             self.R[nd], self.R_r[nd], self.P[nd], self.P_r[nd] = 0, 0, 0, 0
 
         self.unrooted = 0 # parses where we couldn't add_root
+        self.double_heads = 0 # parses w/ two heads to one argument
         self._precision, self._recall, self._precision_r, self._recall_r = 0.0, 0.0, 0.0, 0.0
         self._F1, self._F1_r = 0.0, 0.0
         
@@ -142,15 +141,15 @@ class Evaluation():
         P_rden = self.P['den']+self.P_r['den']
         str_vals = (self.P['num'],self.P['den'],self._precision, P_rnum,P_rden,self._precision_r,
                     self.R['num'],self.R['den'],self._recall,    R_rnum,R_rden,self._recall_r,
-                    self._F1, self._F1_r, self.unrooted)
+                    self._F1, self._F1_r, self.unrooted, self.double_heads)
         regular_str = '''P:  %5d/%5d = %s | P_r:  %5d/%5d = %s
 R:  %5d/%5d = %s | R_r:  %5d/%5d = %s
-F1:               %s | F1_r:               %s (unrooted gold parses: %d)'''%str_vals
+F1:               %s | F1_r:               %s (unrooted gold parses: %d, double-headed: %d)'''%str_vals
 
         tex_str_vals = tuple([p * 100 for p in (self._precision,self._precision_r,self._recall,self._recall_r,self._F1,self._F1_r)])
         tex_str = "$C_A=; C_S=;C_N=;C_M=$   & %.1f (%.1f)   & %.1f (%.1f)    & %.1f (%.1f) \\"%tex_str_vals
 
-        return tex_str # todo
+        return tex_str # todo make variable
                 
         
 
@@ -168,9 +167,12 @@ def evaluate(g, tagged_and_parsed_sents):
     E = Evaluation()
 
     for sent, gold_parse in tagged_and_parsed_sents:
+        if len(sent)-1 != len(gold_parse):
+            E.double_heads += 1
+            continue
         mpp_sent = mpp(g, sent)
         try: gold_parse = add_root(gold_parse)
-        except ValueError: E.unrooted += 1
+        except RuntimeError: E.unrooted += 1
 
         for pair in gold_parse:
             dict = E.R
@@ -274,6 +276,7 @@ def rnd_grammars_test():
                       H,S,N,M)
                     for g,H,S,N,M in rnd_grammars1]
 
+
 if __name__ == "__main__":
     print "main.py:"
     
@@ -287,7 +290,7 @@ if __name__ == "__main__":
                             initialize_loc_h,
                             loc_h_dmv.inner_sent,
                             corpus_size=6268,
-                            iterations=50,
+                            iterations=30,
                             corpus_offset=0,
                             EVAL=True)
         print g 
index 8dd59bf..1f66590 100644 (file)
@@ -161,12 +161,12 @@ def add_root(parse):
     for (head,loc_h) in set([h for h,a in parse]):
         if (head,loc_h) not in set([a for h,a in parse]):
             if rooted:
-                raise ValueError, "Several possible roots in parse: %s"%(list(parse),)
+                raise RuntimeError, "Several possible roots in parse: %s"%(list(parse),)
             else:
                 rooted = (head,loc_h)
 
     if not rooted:
-        raise ValueError, "No root in parse!"
+        raise RuntimeError, "No root in parse!"
     
     rootpair = (MPPROOT, rooted)
     return parse.union(set([ rootpair ]))