/* * EvaluationBasedOnDocs.java * * Yaoyong Li 22/03/2007 * * $Id: EvaluationBasedOnDocs.java, v 1.0 2007-03-22 12:58:16 +0000 yaoyong $ */ package gate.learning; import gate.Annotation; import gate.AnnotationSet; import gate.Corpus; import gate.Document; import gate.Factory; import gate.FeatureMap; import gate.creole.ResourceInstantiationException; import gate.util.AnnotationDiffer; import gate.util.GateException; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.Set; /** * Do evaluation by splitting the documents into training and testing datasets. * Two methods of splitting are implemented, namely k-fold and hold-out test. */ public class EvaluationBasedOnDocs { /** Corpus referring to the corpus used as data. */ Corpus corpusOn; /** Number of documents in the corpus. */ int numDoc; /** * Showing if one document used for training or testing in one evaluation. */ boolean[] isUsedForTraining; /** The sub-directory for storing the data file produced by ML api. */ File wdResults; /** Name of the annotation set as input. */ String inputASName; /** Storing the macro averaged overall F-measure results of the evaluation. */ public EvaluationMeasuresComputation macroMeasuresOfResults = new EvaluationMeasuresComputation(); /** Storing the macro averaged results of every label. */ HashMap labels2MMR = new HashMap(); /** * Label to number of the runs having that label, used for macro-averaged for * each label. */ HashMap labels2RunsNum = new HashMap(); /** * Label to number of the instances with that label, averaged over the number * of runs for that label. */ HashMap labels2InstNum = new HashMap(); /** Constructor. */ public EvaluationBasedOnDocs(Corpus corpus, File wdRes, String inputAsN) { corpusOn = corpus; numDoc = corpus.size(); isUsedForTraining = new boolean[numDoc]; wdResults = wdRes; inputASName = inputAsN; } /** * Main method for evaluation. * * @throws IOException */ public void evaluation(LearningEngineSettings learningSettings, LightWeightLearningApi lightWeightApi) throws GateException, IOException { // first obtain the feature vectors from documents /* * BufferedWriter outNLPFeatures=null; BufferedReader inNLPFeatures = null; * BufferedWriter outFeatureVectors = null; boolean isTraining = true; * outNLPFeatures = new BufferedWriter(new OutputStreamWriter(new * FileOutputStream(new File(wdResults, * ConstantParameters.FILENAMEOFNLPFeaturesData)), "UTF-8")); for(int i = 0; * i < corpusOn.size(); ++i) { Document toProcess= * (Document)corpusOn.get(i); * lightWeightApi.annotations2NLPFeatures(toProcess, i, outNLPFeatures, * isTraining, learningSettings); if(toProcess.getDataStore() != null && * corpusOn.getDataStore() != null) Factory.deleteResource(toProcess); * //++numDoc; } outNLPFeatures.flush(); outNLPFeatures.close(); * lightWeightApi.finishFVs(wdResults, numDoc, isTraining, * learningSettings); // Open the normal NLP feature file. inNLPFeatures = * new BufferedReader(new InputStreamReader(new FileInputStream(new * File(wdResults, ConstantParameters.FILENAMEOFNLPFeaturesData)), * "UTF-8")); outFeatureVectors = new BufferedWriter(new * OutputStreamWriter(new FileOutputStream( new * File(wdResults,ConstantParameters.FILENAMEOFFeatureVectorTotalData)), * "UTF-8")); lightWeightApi.nlpfeatures2FVs(wdResults, inNLPFeatures, * outFeatureVectors, numDoc, isTraining, learningSettings); * inNLPFeatures.close(); outFeatureVectors.flush(); * outFeatureVectors.close(); */ // outFeatureVectors.close(); // k-fold if(learningSettings.evaluationconfig.mode == EvaluationConfiguration.kfold) kfoldEval(learningSettings, lightWeightApi); // Hold-out testing else if(learningSettings.evaluationconfig.mode == EvaluationConfiguration.split) holdoutEval(learningSettings, lightWeightApi); else throw new GateException("The evaluation configuration mode as " + learningSettings.evaluationconfig.mode + " is not implemented!"); StringBuffer logMes = new StringBuffer(); logMes.append("\n*** Averaged results for each label over " + learningSettings.evaluationconfig.kk + " runs as:\n"); logMes.append(printFmeasureForEachLabel(labels2InstNum, labels2MMR)); logMes.append("\nOverall results as:\n"); logMes.append(macroMeasuresOfResults.printResults()); LogService.logMessage(logMes.toString(), 1); if(LogService.minVerbosityLevel > 0) System.out.println(logMes); } /** K-fold evaluation. */ public void kfoldEval(LearningEngineSettings learningSettings, LightWeightLearningApi lightWeightApi) throws GateException { int k = learningSettings.evaluationconfig.kk; LogService.logMessage("K-fold evaluation: k=" + k, 1); int lenPerFold = (new Double(Math.floor((double)numDoc / k))).intValue(); if(lenPerFold < 1) lenPerFold = 1; int beginIndex, endIndex; if(LogService.minVerbosityLevel > 0) { System.out.println("Kfold k=" + new Integer(k) + ", numDoc=" + new Integer(numDoc) + ", len=" + new Integer(lenPerFold) + "."); } LogService.logMessage("Kfold k=" + new Integer(k) + ", numDoc=" + new Integer(numDoc) + ", len=" + new Integer(lenPerFold) + ".", 1); for(int nr = 0; nr < k; ++nr) { EvaluationMeasuresComputation measuresOfResults = new EvaluationMeasuresComputation(); // Label to measure of result of the label HashMap labels2MR = new HashMap(); beginIndex = nr * lenPerFold; endIndex = (nr + 1) * lenPerFold; if(endIndex > numDoc) endIndex = numDoc; if(beginIndex > endIndex) beginIndex = endIndex; int i; for(i = 0; i < beginIndex; ++i) isUsedForTraining[i] = true; for(i = beginIndex; i < endIndex; ++i) isUsedForTraining[i] = false; for(i = endIndex; i < numDoc; ++i) isUsedForTraining[i] = true; StringBuffer logMes = new StringBuffer(); int nr0 = nr + 1; logMes.append("\n*** Fold " + nr0 + "\n"); logMes.append("Number of docs for training: " + (int)(numDoc - endIndex + beginIndex) + "\n"); int ik = 0; for(i = 0; i < numDoc; ++i) { if(isUsedForTraining[i]) { ++ik; Document toProcess = (Document)corpusOn.get(i); logMes .append(ik + " " + toProcess.getName() + "\n"); if(toProcess.getDataStore() != null && corpusOn.getDataStore() != null) Factory.deleteResource(toProcess); } } logMes.append("Number of docs for application: " + (int)(endIndex - beginIndex) + "\n"); ik = 0; for(i = 0; i < numDoc; ++i) { if(!isUsedForTraining[i]) { ++ik; Document toProcess = (Document)corpusOn.get(i); logMes .append(ik + " " + toProcess.getName() + "\n"); if(toProcess.getDataStore() != null && corpusOn.getDataStore() != null) Factory.deleteResource(toProcess); } } LogService.logMessage(logMes.toString(), 1); if(LogService.minVerbosityLevel > 1) System.out.println(logMes); // call the training or application oneRun(learningSettings, lightWeightApi, isUsedForTraining, measuresOfResults, labels2MR, labels2InstNum); // Add to the macro averaged figures add2MacroMeasure(measuresOfResults, labels2MR, macroMeasuresOfResults, labels2MMR, labels2RunsNum); } macroMeasuresOfResults.macroAverage(k); for(Object obj : labels2MMR.keySet()) { int num = new Integer(labels2RunsNum.get(obj).toString()).intValue(); ((EvaluationMeasuresComputation)labels2MMR.get(obj)).macroAverage(num); num = (int)(new Float(labels2InstNum.get(obj).toString()).floatValue() / num); labels2InstNum.put(obj, new Integer(num)); } } /** Hold-out testing. */ public void holdoutEval(LearningEngineSettings learningSettings, LightWeightLearningApi lightWeightApi) throws GateException { int k = learningSettings.evaluationconfig.kk; LogService.logMessage("Hold-out test: runs=" + k + ", ratio of training docs is " + learningSettings.evaluationconfig.ratio, 1); int trainingNum = (new Double(Math .floor((numDoc * learningSettings.evaluationconfig.ratio))).intValue()); if(trainingNum > numDoc) trainingNum = numDoc; LogService.logMessage("Split, k=" + new Integer(k) + ", trainingNum=" + new Integer(trainingNum) + ".", 1); if(LogService.minVerbosityLevel > 0) { System.out.println("Hold-out test: runs=" + k + ", ratio of training docs is " + learningSettings.evaluationconfig.ratio); System.out.println("Split, k=" + new Integer(k) + ", trainingNum=" + new Integer(trainingNum) + "."); } int testNum = numDoc - trainingNum; Random randGenerator = new Random(1000); for(int nr = 0; nr < k; ++nr) { EvaluationMeasuresComputation measuresOfResults = new EvaluationMeasuresComputation(); // Label to measure of result of the label HashMap labels2MR = new HashMap(); // Select the training examples randomly from the data int[] indexRand = new int[testNum]; for(int i = 0; i < testNum; ++i) { int newNum = 0; boolean isDuplicate = true; int maxNumSel = 0; while(isDuplicate && maxNumSel < 1000) { newNum = randGenerator.nextInt(numDoc); isDuplicate = false; for(int j = 0; j < i; ++j) if(indexRand[j] == newNum) { isDuplicate = true; break; } } if(isDuplicate) { // If cannot select a non-duplicate index in // 1000 times, selected the one boolean isOk = false; for(int j = 0; j < numDoc; ++j) { for(int j1 = 0; j1 < i; ++j1) if(indexRand[j1] != j) { newNum = j; isOk = true; break; } if(isOk) break; } } if(LogService.minVerbosityLevel > 1) { System.out.println("i=" + new Integer(i) + ", newNum=" + new Integer(newNum)); } indexRand[i] = newNum; } for(int i = 0; i < numDoc; ++i) isUsedForTraining[i] = true; for(int i = 0; i < testNum; ++i) isUsedForTraining[indexRand[i]] = false; StringBuffer logMes = new StringBuffer(); int nr0 = nr + 1; logMes.append("\n*** Run " + nr0 + "\n"); logMes.append("Number of docs for training: " + (int)(numDoc - testNum) + "\n"); int ik = 0; for(int i = 0; i < numDoc; ++i) { if(isUsedForTraining[i]) { ++ik; Document toProcess = (Document)corpusOn.get(i); logMes .append(ik + " " + toProcess.getName() + "\n"); if(toProcess.getDataStore() != null && corpusOn.getDataStore() != null) Factory.deleteResource(toProcess); } } logMes.append("Number of docs for application: " + testNum + "\n"); ik = 0; for(int i = 0; i < numDoc; ++i) { if(!isUsedForTraining[i]) { ++ik; Document toProcess = (Document)corpusOn.get(i); logMes .append(ik + " " + toProcess.getName() + "\n"); if(toProcess.getDataStore() != null && corpusOn.getDataStore() != null) Factory.deleteResource(toProcess); } } LogService.logMessage(logMes.toString(), 1); if(LogService.minVerbosityLevel > 1) System.out.println(logMes); // One run, call the training and application and do evaluation oneRun(learningSettings, lightWeightApi, isUsedForTraining, measuresOfResults, labels2MR, labels2InstNum); // Add to the macro averaged figures add2MacroMeasure(measuresOfResults, labels2MR, macroMeasuresOfResults, labels2MMR, labels2RunsNum); } macroMeasuresOfResults.macroAverage(k); for(Object obj : labels2MMR.keySet()) { int num = new Integer(labels2RunsNum.get(obj).toString()).intValue(); ((EvaluationMeasuresComputation)labels2MMR.get(obj)).macroAverage(num); // Averaged the number of instances for all the runs num = (int)(new Float(labels2InstNum.get(obj).toString()).floatValue() / num); labels2InstNum.put(obj, new Integer(num)); } } /** * One run of the evaluation: training, testing and measuring results. * * @throws * @throws UnsupportedEncodingException */ private void oneRun(LearningEngineSettings learningSettings, LightWeightLearningApi lightWeightApi, boolean isUsedForTraining[], EvaluationMeasuresComputation measuresOfResults, HashMap labels2MR, HashMap labels2InstNum) throws GateException { // first learning using the document for training // empty the data file emptyDatafile(wdResults, true); lightWeightApi.labelsAndId.clearAllData(); lightWeightApi.featuresList.clearAllData(); boolean isTraining = true; int numDoc = 0; BufferedWriter outNLPFeatures = null; BufferedReader inNLPFeatures = null; BufferedWriter outFeatureVectors = null; try { outNLPFeatures = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(new File(wdResults, ConstantParameters.FILENAMEOFNLPFeaturesData)), "UTF-8")); for(int i = 0; i < corpusOn.size(); ++i) if(isUsedForTraining[i]) { Document toProcess = (Document)corpusOn.get(i); lightWeightApi.annotations2NLPFeatures(toProcess, numDoc, outNLPFeatures, isTraining, learningSettings); if(toProcess.getDataStore() != null && corpusOn.getDataStore() != null) Factory.deleteResource(toProcess); ++numDoc; } outNLPFeatures.flush(); outNLPFeatures.close(); lightWeightApi.finishFVs(wdResults, numDoc, isTraining, learningSettings); // Open the normal NLP feature file. inNLPFeatures = new BufferedReader(new InputStreamReader( new FileInputStream(new File(wdResults, ConstantParameters.FILENAMEOFNLPFeaturesData)), "UTF-8")); outFeatureVectors = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(new File(wdResults, ConstantParameters.FILENAMEOFFeatureVectorData)), "UTF-8")); lightWeightApi.nlpfeatures2FVs(wdResults, inNLPFeatures, outFeatureVectors, numDoc, isTraining, learningSettings); inNLPFeatures.close(); outFeatureVectors.flush(); outFeatureVectors.close(); // outFeatureVectors.close(); // read the fv data from total file and write them into fv files for // training and application, respectively /* * BufferedReader inFVs = new BufferedReader(new InputStreamReader(new * FileInputStream(new File(wdResults, * ConstantParameters.FILENAMEOFFeatureVectorTotalData)), "UTF-8")); * BufferedWriter outFVs = new BufferedWriter(new OutputStreamWriter(new * FileOutputStream( new * File(wdResults,ConstantParameters.FILENAMEOFFeatureVectorData)), * "UTF-8")); BufferedWriter outFVsApp = new BufferedWriter(new * OutputStreamWriter(new FileOutputStream( new * File(wdResults,ConstantParameters.FILENAMEOFFeatureVectorDataApp)), * "UTF-8")); for(int i = 0; i < corpusOn.size(); ++i) { String str = * inFVs.readLine(); int numLines = * Integer.parseInt(str.substring(str.indexOf(ConstantParameters.ITEMSEPARATOR)+1, * str.lastIndexOf(ConstantParameters.ITEMSEPARATOR))); * if(isUsedForTraining[i]) { outFVs.append(str); outFVs.newLine(); * for(int j=0; j<numLines; ++j) { outFVs.append(inFVs.readLine()); * outFVs.newLine(); } ++numDoc; } else { outFVsApp.append(str); * outFVsApp.newLine(); for(int j=0; j<numLines; ++j) { * outFVsApp.append(inFVs.readLine()); outFVsApp.newLine(); } } } * inFVs.close(); outFVs.flush(); outFVs.close(); outFVsApp.flush(); * outFVsApp.close(); */ // if fitering the training data if(learningSettings.fiteringTrainingData && learningSettings.filteringRatio > 0.0) lightWeightApi.FilteringNegativeInstsInJava(numDoc, learningSettings); // lightWeightApi.trainDirect(); lightWeightApi.trainingJava(numDoc, learningSettings); // then application to the test set // First we empty the NLP feature file and feature vector file; but not // the list files. emptyDatafile(wdResults, false); // We have to use two class types for the evaluation purpose String classTypeOriginal = null; String classTypeTest = null; String classFeature = null; classTypeOriginal = learningSettings.datasetDefinition .getClassAttribute().getType(); classTypeTest = classTypeOriginal.concat("Test"); classFeature = learningSettings.datasetDefinition.getClassAttribute() .getFeature(); learningSettings.datasetDefinition.getClassAttribute().setType( classTypeTest); if(LogService.minVerbosityLevel > 1) System.out.println("classType=" + classTypeOriginal + ", testType=" + classTypeTest + "."); isTraining = false; // numDoc = isUsedForTraining.length - numDoc; numDoc = 0; outNLPFeatures = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(new File(wdResults, ConstantParameters.FILENAMEOFNLPFeaturesData)), "UTF-8")); for(int i = 0; i < corpusOn.size(); ++i) if(!isUsedForTraining[i]) { Document toProcess = (Document)corpusOn.get(i); lightWeightApi.annotations2NLPFeatures(toProcess, numDoc, outNLPFeatures, isTraining, learningSettings); ++numDoc; if(toProcess.getDataStore() != null && corpusOn.getDataStore() != null) { corpusOn.getDataStore().sync(corpusOn); Factory.deleteResource(toProcess); } } outNLPFeatures.flush(); outNLPFeatures.close(); lightWeightApi.finishFVs(wdResults, numDoc, isTraining, learningSettings); inNLPFeatures = new BufferedReader(new InputStreamReader( new FileInputStream(new File(wdResults, ConstantParameters.FILENAMEOFNLPFeaturesData)), "UTF-8")); outFeatureVectors = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(new File(wdResults, ConstantParameters.FILENAMEOFFeatureVectorDataApp)), "UTF-8")); lightWeightApi.nlpfeatures2FVs(wdResults, inNLPFeatures, outFeatureVectors, numDoc, isTraining, learningSettings); inNLPFeatures.close(); outFeatureVectors.flush(); outFeatureVectors.close(); // lightWeightApi.finishDocAnnotation(); Corpus corpusTest; corpusTest = Factory.newCorpus("testCorpus"); if(corpusOn.getDataStore() != null) { Corpus corpusTestTemp = (Corpus)corpusOn.getDataStore().adopt(corpusTest, null); Factory.deleteResource(corpusTest); corpusTest = corpusTestTemp; corpusTest.getDataStore().sync(corpusTest); } numDoc = 0; for(int i = 0; i < corpusOn.size(); ++i) if(!isUsedForTraining[i]) { Document d = (Document)corpusOn.get(i); corpusTest.add(d); if(corpusTest.getDataStore() != null) { corpusTest.getDataStore().sync(corpusTest); Factory.deleteResource(d); } ++numDoc; } String fvFileName = wdResults.toString() + File.separator + ConstantParameters.FILENAMEOFFeatureVectorDataApp; lightWeightApi.applyModelInJava(corpusTest, 0, corpusTest.size(), classTypeTest, learningSettings, fvFileName); //unload the documents in the test corpus from memory /*for(int i=0; i<corpusTest.size(); ++i) { Document toProcess = (Document)corpusOn.get(i); if(corpusOn.getDataStore() != null) { corpusOn.getDataStore().sync(corpusOn); Factory.deleteResource(toProcess); } }*/ corpusTest.clear(); Factory.deleteResource(corpusTest); if(corpusTest.getDataStore() != null) { corpusTest.getDataStore().delete(corpusTest.getClass().getName(), corpusTest.getLRPersistenceId()); } // Do the evaluation on test using the AnnotationDiff // First get all the labels in the training data, // so that we can do evaluation on each single label // as well as on all labels HashMap uniqueLabels = new HashMap(); for(int i = 0; i < corpusOn.size(); ++i) if(isUsedForTraining[i]) { Document toProcess = (Document)corpusOn.get(i); AnnotationSet keyAnns = getInputAS(toProcess).get(classTypeOriginal); for(Object obj : keyAnns) { if(((Annotation)obj).getFeatures().get(classFeature) != null) { String label = ((Annotation)obj).getFeatures().get(classFeature) .toString(); if(uniqueLabels.containsKey(label)) uniqueLabels.put(label, new Integer(new Integer(uniqueLabels .get(label).toString()).intValue() + 1)); else uniqueLabels.put(label, "1"); } } if(toProcess.getDataStore() != null && corpusOn.getDataStore() != null) { corpusOn.getDataStore().sync(corpusOn); Factory.deleteResource(toProcess); } } // Then create one evaluationMeasure object for each label for(Object obj : uniqueLabels.keySet()) { EvaluationMeasuresComputation emc = new EvaluationMeasuresComputation(); labels2MR.put(obj, emc); } // Copy the number of instances for each label into the macro one for(Object obj : uniqueLabels.keySet()) { if(labels2InstNum.containsKey(obj)) { int num = new Integer(uniqueLabels.get(obj).toString()).intValue(); labels2InstNum.put(obj, new Integer(new Integer(labels2InstNum.get( obj).toString()).intValue() + num)); } else labels2InstNum.put(obj, uniqueLabels.get(obj)); } // Do the evaluation on the test set if(learningSettings.datasetDefinition.dataType == DataSetDefinition.RelationData) { // For relation type, we cannot use the evaluation method AnnDiff // of Gate AttributeRelation relAttr = (AttributeRelation)learningSettings.datasetDefinition .getClassAttribute(); String arg1F = relAttr.getArg1(); String arg2F = relAttr.getArg2(); for(int i = 0; i < corpusOn.size(); ++i) { if(!isUsedForTraining[i]) { Document toProcess = (Document)corpusOn.get(i); evaluateAnnotationsRel(toProcess, classTypeOriginal, classTypeTest, classFeature, arg1F, arg2F, uniqueLabels.keySet(), labels2MR); if(toProcess.getDataStore() != null && corpusOn.getDataStore() != null) { corpusOn.getDataStore().sync(corpusOn); Factory.deleteResource(toProcess); } } } } else { /* * for(int i=0; i<corpusOn.size(); ++i) { if(! isUsedForTraining[i]) { * evaluateAnnotations((Document)corpusOn.get(i), classTypeOriginal, * classTypeTest, classFeature, uniqueLabels.keySet(), labels2MR); } } */ // evaluation on each label using the AnnDiff method of Gate for(int i = 0; i < corpusOn.size(); ++i) if(!isUsedForTraining[i]) { Document toProcess = (Document)corpusOn.get(i); evaluateAnnDiff(toProcess, classTypeOriginal, classTypeTest, classFeature, uniqueLabels.keySet(), labels2MR); if(toProcess.getDataStore() != null && corpusOn.getDataStore() != null) { corpusOn.getDataStore().sync(corpusOn); Factory.deleteResource(toProcess); } } } // Pool the results of all labels together for(Object obj : uniqueLabels.keySet()) measuresOfResults .add((EvaluationMeasuresComputation)labels2MR.get(obj)); measuresOfResults.computeFmeasure(); measuresOfResults.computeFmeasureLenient(); for(Object obj : uniqueLabels.keySet()) { EvaluationMeasuresComputation emc = (EvaluationMeasuresComputation)labels2MR .get(obj); emc.computeFmeasure(); emc.computeFmeasureLenient(); } StringBuffer logMes = new StringBuffer(); logMes.append("Results of this run:\n\n"); logMes.append(printFmeasureForEachLabel(uniqueLabels, labels2MR)); logMes.append("\nOverall results(micro-averaged over all labels):\n"); logMes.append(measuresOfResults.printResults()); if(LogService.minVerbosityLevel > 1) { System.out.println(logMes); } LogService.logMessage(logMes.toString(), 1); // finally, change the class type back for training, // and remove the test annotations learningSettings.datasetDefinition.getClassAttribute().setType( classTypeOriginal); for(int i = 0; i < corpusOn.size(); ++i) { if(!isUsedForTraining[i]) { Document toProcess = (Document)corpusOn.get(i); AnnotationSet annsInput = getInputAS(toProcess); AnnotationSet anns = annsInput.get(classTypeTest); Iterator iter = anns.iterator(); while(iter.hasNext()) annsInput.remove((Annotation)iter.next()); if(toProcess.getDataStore() != null && corpusOn.getDataStore() != null) { corpusOn.getDataStore().sync(corpusOn); Factory.deleteResource(toProcess); } } } } catch(ResourceInstantiationException e) { e.printStackTrace(); } catch(UnsupportedEncodingException e1) { e1.printStackTrace(); } catch(FileNotFoundException e1) { e1.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } } /** Empty the label list and feature list. */ public static void emptyDatafile(File wdResults, boolean isRemoveList) { if(isRemoveList) { (new File(wdResults, ConstantParameters.FILENAMEOFNLPFeatureList)) .delete(); (new File(wdResults, ConstantParameters.FILENAMEOFLabelList)).delete(); (new File(wdResults, ConstantParameters.FILENAMEOFChunkLenStats)) .delete(); (new File(wdResults, ConstantParameters.FILENAMEOFLabelsInData)).delete(); try { (new File(wdResults, ConstantParameters.FILENAMEOFNLPFeatureList)) .createNewFile(); } catch(IOException e) { e.printStackTrace(); } } (new File(wdResults, ConstantParameters.FILENAMEOFNLPFeaturesData)) .delete(); (new File(wdResults, ConstantParameters.FILENAMEOFFeatureVectorData)) .delete(); (new File(wdResults, ConstantParameters.FILENAMEOFNLPDataLabel)).delete(); System.gc(); // to make effort to delete the files. } /** Add the F-measure of each label to the overal F-measure */ public void add2MacroMeasure(EvaluationMeasuresComputation measuresOfResults, HashMap labels2MR, EvaluationMeasuresComputation macroMeasuresOfResults, HashMap labels2MMR, HashMap labels2RunsNum) { macroMeasuresOfResults.add(measuresOfResults); // for each label for(Object obj : labels2MR.keySet()) { String label = obj.toString(); if(labels2MMR.containsKey(label)) {// the label is in the macro // Array already ((EvaluationMeasuresComputation)labels2MMR.get(label)) .add(((EvaluationMeasuresComputation)(labels2MR.get(label)))); labels2RunsNum.put(label, new Integer((new Integer(labels2RunsNum.get( label).toString()).intValue() + 1))); } else { // labels2MMR.put(label, new EvaluationMeasuresComputation()); EvaluationMeasuresComputation emc = new EvaluationMeasuresComputation(); emc.add((EvaluationMeasuresComputation)(labels2MR.get(label))); labels2MMR.put(label, emc); labels2RunsNum.put(label, "1"); } } } /** Print the F-measure results for each label. */ public String printFmeasureForEachLabel(HashMap uniqueLabels, HashMap labels2MR) { StringBuffer logMes = new StringBuffer(); logMes.append("\nResults of single label:\n"); // LogService.logMessage("\nResults of single label", 1); List labels = new ArrayList(uniqueLabels.keySet()); Collections.sort(labels); for(int i = 0; i < labels.size(); ++i) { String labelName = labels.get(i).toString(); logMes.append(i + " LabelName=" + labelName + ", number of instances=" + new Integer(uniqueLabels.get(labelName).toString()) + "\n"); logMes.append(((EvaluationMeasuresComputation)labels2MR.get(labelName)) .printResults()); // ((EvaluationMeasuresComputation)labels2MR.get(labelName)) // .printResults(logFileIn); } return logMes.toString(); } /** Evaluate the test document by using the AnnotationDiff class. */ public void evaluateAnnDiff(Document doc, String classTypeOriginal, String classTypeTest, String classFeat, Set labelSet, HashMap labels2MR) { // for each label AnnotationSet annsOriginal = getInputAS(doc).get(classTypeOriginal); AnnotationSet annsTest = getInputAS(doc).get(classTypeTest); HashSet annsKey = new HashSet(); HashSet annsRes = new HashSet(); HashSet signSet = new HashSet(); signSet.add(classFeat); for(Object obj : labelSet) { String label = obj.toString(); annsKey.clear(); annsRes.clear(); for(Object objAnn : annsOriginal) if(((FeatureMap)((Annotation)objAnn).getFeatures()).get(classFeat) != null) if(((FeatureMap)((Annotation)objAnn).getFeatures()).get(classFeat) .toString().equals(label)) annsKey.add(objAnn); for(Object objAnn : annsTest) if(((FeatureMap)((Annotation)objAnn).getFeatures()).get(classFeat) != null) if(((FeatureMap)((Annotation)objAnn).getFeatures()).get(classFeat) .toString().equals(label)) annsRes.add(objAnn); AnnotationDiffer annDiff = new AnnotationDiffer(); annDiff.setSignificantFeaturesSet(signSet); annDiff.calculateDiff(annsKey, annsRes); EvaluationMeasuresComputation emc = (EvaluationMeasuresComputation)labels2MR .get(label); emc.correct += annDiff.getCorrectMatches(); emc.partialCor += annDiff.getPartiallyCorrectMatches(); emc.missing += annDiff.getMissing(); emc.spurious += annDiff.getSpurious(); } } /** * Evaluate the test document by comparing the annotations with the golden * standard */ public void evaluateAnnotations(Document doc, String classTypeOriginal, String classTypeTest, String classFeat, Set labelSet, HashMap labels2MR) { AnnotationSet annsOriginal = getInputAS(doc).get(classTypeOriginal); AnnotationSet annsTest = getInputAS(doc).get(classTypeTest); HashSet annsKey = new HashSet(); HashSet annsRes = new HashSet(); // For each label for(Object obj : labelSet) { String label = obj.toString(); annsKey.clear(); annsRes.clear(); for(Object objAnn : annsOriginal) { Object label0 = ((Annotation)objAnn).getFeatures().get(classFeat); if(label0 != null && label0.equals(label)) annsKey.add(objAnn); } for(Object objAnn : annsTest) { Object label0 = ((Annotation)objAnn).getFeatures().get(classFeat); if(label0 != null && label0.equals(label)) annsRes.add(objAnn); } EvaluationMeasuresComputation measuresOfResults = (EvaluationMeasuresComputation)labels2MR .get(label); for(Object annOrig : annsKey) { boolean isMatch = false; for(Object annTest : annsRes) if(((Annotation)annTest).coextensive(((Annotation)annOrig))) { measuresOfResults.correct++; isMatch = true; break; } if(!isMatch) measuresOfResults.missing++; } for(Object annTest : annsRes) { boolean isMatch = false; for(Object annOrig : annsKey) if(((Annotation)annTest).coextensive(((Annotation)annOrig))) { isMatch = true; break; } if(!isMatch) measuresOfResults.spurious++; } } } /** * Evaluate the test document by comparing the annotations with the golden * standard, for Relation learning */ public void evaluateAnnotationsRel(Document doc, String classTypeOriginal, String classTypeTest, String classFeat, String arg1F, String arg2F, Set labelSet, HashMap labels2MR) { AnnotationSet annsOriginal = getInputAS(doc).get(classTypeOriginal); AnnotationSet annsTest = getInputAS(doc).get(classTypeTest); HashSet annsKey = new HashSet(); HashSet annsRes = new HashSet(); // For each label for(Object obj : labelSet) { String label = obj.toString(); annsKey.clear(); annsRes.clear(); for(Object objAnn : annsOriginal) { Object label0 = ((Annotation)objAnn).getFeatures().get(classFeat); if(label0 != null && label0.equals(label)) annsKey.add(objAnn); } for(Object objAnn : annsTest) { Object label0 = ((Annotation)objAnn).getFeatures().get(classFeat); if(label0 != null && label0.equals(label)) annsRes.add(objAnn); } EvaluationMeasuresComputation measuresOfResults = (EvaluationMeasuresComputation)labels2MR .get(label); for(Object annOrig : annsKey) { Object arg1VO = ((Annotation)annOrig).getFeatures().get(arg1F); Object arg2VO = ((Annotation)annOrig).getFeatures().get(arg2F); boolean isMatch = false; for(Object annTest : annsRes) { FeatureMap feats = ((Annotation)annTest).getFeatures(); if(arg1VO.equals(feats.get(arg1F)) && arg2VO.equals(feats.get(arg2F))) { measuresOfResults.correct++; isMatch = true; break; } } if(!isMatch) measuresOfResults.missing++; } for(Object annTest : annsRes) { Object arg1VO = ((Annotation)annTest).getFeatures().get(arg1F); Object arg2VO = ((Annotation)annTest).getFeatures().get(arg2F); boolean isMatch = false; for(Object annOrig : annsKey) { FeatureMap feats = ((Annotation)annOrig).getFeatures(); if(arg1VO.equals(feats.get(arg1F)) && arg2VO.equals(feats.get(arg2F))) { isMatch = true; break; } } if(!isMatch) measuresOfResults.spurious++; } } } private AnnotationSet getInputAS(Document doc) { if(inputASName == null || inputASName.trim().length() == 0) { return doc.getAnnotations(); } else { return doc.getAnnotations(inputASName); } } }