public virtual void ProcessResults(IParserQuery pq, Tree goldTree, PrintWriter pwErr, PrintWriter pwOut, PrintWriter pwFileOut, PrintWriter pwStats, TreePrint treePrint) { if (pq.SaidMemMessage()) { saidMemMessage = true; } Tree tree; IList <IHasWord> sentence = pq.OriginalSentence(); try { tree = pq.GetBestParse(); } catch (NoSuchParseException) { tree = null; } IList <ScoredObject <Tree> > kbestPCFGTrees = null; if (tree != null && kbestPCFG > 0) { kbestPCFGTrees = pq.GetKBestPCFGParses(kbestPCFG); } //combo parse goes to pwOut (System.out) if (op.testOptions.verbose) { pwOut.Println("ComboParser best"); Tree ot = tree; if (ot != null && !op.tlpParams.TreebankLanguagePack().IsStartSymbol(ot.Value())) { ot = ot.TreeFactory().NewTreeNode(op.tlpParams.TreebankLanguagePack().StartSymbol(), Java.Util.Collections.SingletonList(ot)); } treePrint.PrintTree(ot, pwOut); } else { treePrint.PrintTree(tree, pwOut); } // **OUTPUT** // print various n-best like outputs (including 1-best) // print various statistics if (tree != null) { if (op.testOptions.printAllBestParses) { IList <ScoredObject <Tree> > parses = pq.GetBestPCFGParses(); int sz = parses.Count; if (sz > 1) { pwOut.Println("There were " + sz + " best PCFG parses with score " + parses[0].Score() + '.'); Tree transGoldTree = collinizer.TransformTree(goldTree); int iii = 0; foreach (ScoredObject <Tree> sot in parses) { iii++; Tree tb = sot.Object(); Tree tbd = debinarizer.TransformTree(tb); tbd = subcategoryStripper.TransformTree(tbd); pq.RestoreOriginalWords(tbd); pwOut.Println("PCFG Parse #" + iii + " with score " + tbd.Score()); tbd.PennPrint(pwOut); Tree tbtr = collinizer.TransformTree(tbd); // pwOut.println("Tree size = " + tbtr.size() + "; depth = " + tbtr.depth()); kGoodLB.Evaluate(tbtr, transGoldTree, pwErr); } } } else { // Huang and Chiang (2006) Algorithm 3 output from the PCFG parser if (op.testOptions.printPCFGkBest > 0 && op.testOptions.outputkBestEquivocation == null) { IList <ScoredObject <Tree> > trees = kbestPCFGTrees.SubList(0, op.testOptions.printPCFGkBest); Tree transGoldTree = collinizer.TransformTree(goldTree); int i = 0; foreach (ScoredObject <Tree> tp in trees) { i++; pwOut.Println("PCFG Parse #" + i + " with score " + tp.Score()); Tree tbd = tp.Object(); tbd.PennPrint(pwOut); Tree tbtr = collinizer.TransformTree(tbd); kGoodLB.Evaluate(tbtr, transGoldTree, pwErr); } } else { // Chart parser (factored) n-best list if (op.testOptions.printFactoredKGood > 0 && pq.HasFactoredParse()) { // DZ: debug n best trees IList <ScoredObject <Tree> > trees = pq.GetKGoodFactoredParses(op.testOptions.printFactoredKGood); Tree transGoldTree = collinizer.TransformTree(goldTree); int ii = 0; foreach (ScoredObject <Tree> tp in trees) { ii++; pwOut.Println("Factored Parse #" + ii + " with score " + tp.Score()); Tree tbd = tp.Object(); tbd.PennPrint(pwOut); Tree tbtr = collinizer.TransformTree(tbd); kGoodLB.Evaluate(tbtr, transGoldTree, pwOut); } } else { //1-best output if (pwFileOut != null) { pwFileOut.Println(tree.ToString()); } } } } //Print the derivational entropy if (op.testOptions.outputkBestEquivocation != null && op.testOptions.printPCFGkBest > 0) { IList <ScoredObject <Tree> > trees = kbestPCFGTrees.SubList(0, op.testOptions.printPCFGkBest); double[] logScores = new double[trees.Count]; int treeId = 0; foreach (ScoredObject <Tree> kBestTree in trees) { logScores[treeId++] = kBestTree.Score(); } //Re-normalize double entropy = 0.0; double denom = ArrayMath.LogSum(logScores); foreach (double logScore in logScores) { double logPr = logScore - denom; entropy += System.Math.Exp(logPr) * (logPr / System.Math.Log(2)); } entropy *= -1; //Convert to bits pwStats.Printf("%f\t%d\t%d\n", entropy, trees.Count, sentence.Count); } } // **EVALUATION** // Perform various evaluations specified by the user if (tree != null) { //Strip subcategories and remove punctuation for evaluation tree = subcategoryStripper.TransformTree(tree); Tree treeFact = collinizer.TransformTree(tree); //Setup the gold tree if (op.testOptions.verbose) { pwOut.Println("Correct parse"); treePrint.PrintTree(goldTree, pwOut); } Tree transGoldTree = collinizer.TransformTree(goldTree); if (transGoldTree != null) { transGoldTree = subcategoryStripper.TransformTree(transGoldTree); } //Can't do evaluation in these two cases if (transGoldTree == null) { pwErr.Println("Couldn't transform gold tree for evaluation, skipping eval. Gold tree was:"); goldTree.PennPrint(pwErr); numSkippedEvals++; return; } else { if (treeFact == null) { pwErr.Println("Couldn't transform hypothesis tree for evaluation, skipping eval. Tree was:"); tree.PennPrint(pwErr); numSkippedEvals++; return; } else { if (treeFact.Yield().Count != transGoldTree.Yield().Count) { IList <ILabel> fYield = treeFact.Yield(); IList <ILabel> gYield = transGoldTree.Yield(); pwErr.Println("WARNING: Evaluation could not be performed due to gold/parsed yield mismatch."); pwErr.Printf(" sizes: gold: %d (transf) %d (orig); parsed: %d (transf) %d (orig).%n", gYield.Count, goldTree.Yield().Count, fYield.Count, tree.Yield().Count); pwErr.Println(" gold: " + SentenceUtils.ListToString(gYield, true)); pwErr.Println(" pars: " + SentenceUtils.ListToString(fYield, true)); numSkippedEvals++; return; } } } if (topKEvals.Count > 0) { IList <Tree> transGuesses = new List <Tree>(); int kbest = System.Math.Min(op.testOptions.evalPCFGkBest, kbestPCFGTrees.Count); foreach (ScoredObject <Tree> guess in kbestPCFGTrees.SubList(0, kbest)) { transGuesses.Add(collinizer.TransformTree(guess.Object())); } foreach (BestOfTopKEval eval in topKEvals) { eval.Evaluate(transGuesses, transGoldTree, pwErr); } } //PCFG eval Tree treePCFG = pq.GetBestPCFGParse(); if (treePCFG != null) { Tree treePCFGeval = collinizer.TransformTree(treePCFG); if (pcfgLB != null) { pcfgLB.Evaluate(treePCFGeval, transGoldTree, pwErr); } if (pcfgChildSpecific != null) { pcfgChildSpecific.Evaluate(treePCFGeval, transGoldTree, pwErr); } if (pcfgLA != null) { pcfgLA.Evaluate(treePCFGeval, transGoldTree, pwErr); } if (pcfgCB != null) { pcfgCB.Evaluate(treePCFGeval, transGoldTree, pwErr); } if (pcfgDA != null) { // Re-index the leaves after Collinization, stripping traces, etc. treePCFGeval.IndexLeaves(true); transGoldTree.IndexLeaves(true); pcfgDA.Evaluate(treePCFGeval, transGoldTree, pwErr); } if (pcfgTA != null) { pcfgTA.Evaluate(treePCFGeval, transGoldTree, pwErr); } if (pcfgLL != null && pq.GetPCFGParser() != null) { pcfgLL.RecordScore(pq.GetPCFGParser(), pwErr); } if (pcfgRUO != null) { pcfgRUO.Evaluate(treePCFGeval, transGoldTree, pwErr); } if (pcfgCUO != null) { pcfgCUO.Evaluate(treePCFGeval, transGoldTree, pwErr); } if (pcfgCatE != null) { pcfgCatE.Evaluate(treePCFGeval, transGoldTree, pwErr); } } //Dependency eval // todo: is treeDep really useful here, or should we really use depDAEval tree (debinarized) throughout? We use it for parse, and it sure seems like we could use it for tag eval, but maybe not factDA? Tree treeDep = pq.GetBestDependencyParse(false); if (treeDep != null) { Tree goldTreeB = binarizerOnly.TransformTree(goldTree); Tree goldTreeEval = goldTree.DeepCopy(); goldTreeEval.IndexLeaves(true); goldTreeEval.PercolateHeads(op.Langpack().HeadFinder()); Tree depDAEval = pq.GetBestDependencyParse(true); depDAEval.IndexLeaves(true); depDAEval.PercolateHeadIndices(); if (depDA != null) { depDA.Evaluate(depDAEval, goldTreeEval, pwErr); } if (depTA != null) { Tree undoneTree = debinarizer.TransformTree(treeDep); undoneTree = subcategoryStripper.TransformTree(undoneTree); pq.RestoreOriginalWords(undoneTree); // pwErr.println("subcategoryStripped tree: " + undoneTree.toStructureDebugString()); depTA.Evaluate(undoneTree, goldTree, pwErr); } if (depLL != null && pq.GetDependencyParser() != null) { depLL.RecordScore(pq.GetDependencyParser(), pwErr); } Tree factTreeB; if (pq.HasFactoredParse()) { factTreeB = pq.GetBestFactoredParse(); } else { factTreeB = treeDep; } if (factDA != null) { factDA.Evaluate(factTreeB, goldTreeB, pwErr); } } //Factored parser (1best) eval if (factLB != null) { factLB.Evaluate(treeFact, transGoldTree, pwErr); } if (factChildSpecific != null) { factChildSpecific.Evaluate(treeFact, transGoldTree, pwErr); } if (factLA != null) { factLA.Evaluate(treeFact, transGoldTree, pwErr); } if (factTA != null) { factTA.Evaluate(tree, boundaryRemover.TransformTree(goldTree), pwErr); } if (factLL != null && pq.GetFactoredParser() != null) { factLL.RecordScore(pq.GetFactoredParser(), pwErr); } if (factCB != null) { factCB.Evaluate(treeFact, transGoldTree, pwErr); } foreach (IEval eval_1 in evals) { eval_1.Evaluate(treeFact, transGoldTree, pwErr); } if (parserQueryEvals != null) { foreach (IParserQueryEval eval in parserQueryEvals) { eval_1.Evaluate(pq, transGoldTree, pwErr); } } if (op.testOptions.evalb) { // empty out scores just in case NanScores(tree); EvalbFormatWriter.WriteEVALBline(treeFact, transGoldTree); } } pwErr.Println(); }