/** * <p> * @author Written by Juan Carlos Fernández and Pedro Antonio Gutiérrez (University of Córdoba) 23/08/2009 * @version 1.0 * @since JDK1.5 * </p> */ package keel.GraphInterKeel.experiments; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.StringTokenizer; import org.jdom.Element; public class EducationalMethodReport extends EducationalReport { /** * <p> * This class creates a report in the experiment directory. * A file "report.txt" is creates in the same result directory. * The report is for methods. * </p> */ private String[] classes = null; //training and test private String set = ""; private int[][] confusionMatrix = null; private int n_partition = -1; private List<Double> listECMParticion=null; private double ecmBest = 0.0, ecmAverage = 0.0, ecmDeviation = 0; /** * <p> * Constructor * </p> * @param sentences Total of sentences for RunKeel.xml * @param experimentType Type of experiment, classification o regression */ public EducationalMethodReport(ArrayList<Element> sentences, int experimentType) { super(sentences, experimentType); } /** * <p> * This method has to invoque for to create the report. * Verify the type of problem, type partition and paths for * to create the report. Read in iterative way the files of * results * </p> */ public void running() { StringTokenizer st = null; int totalGoods = 0; int totalInstances = 0; String partitionPercentages = ""; String cuadraticPartitionPercentages = ""; double totalPercentage = 0.0; String relation = ""; double ecmTotal = 0.0; if(experimentType == CLASSIFICATION) this.calculateClasses(); String modelContents=""; //read model if(listPathFilesExtra.size()>0){ modelContents+="\n\n===================================\n Model generated \n===================================\n"; modelContents+=Files.readFile((String)listPathFilesExtra.get(0)); } else{ modelContents+="\n\nThis method does not provide information about its model.\n"; } //for training and test for (int p=0; p<2; p++) { totalInstances = 0; totalGoods = 0; partitionPercentages = ""; cuadraticPartitionPercentages = ""; ecmTotal = 0.0; String hoped = ""; String obtained = ""; int instancesNumber = 0; n_partition = 0; ecmBest = 0.0; ecmAverage = 0.0; ecmDeviation = 0; listECMParticion = new ArrayList<Double>(); if (p==0) set = "training"; else set = "test"; //for each file for (int i=p; i<pathOutputFiles.length; i = i+2) { n_partition++; try { fr = new FileReader(pathOutputFiles[i]); br = new BufferedReader(fr); } catch (FileNotFoundException e) { e.printStackTrace(); } switch (experimentType) { case CLASSIFICATION: int goods = 0; String cad = ""; instancesNumber = 0; //> double partialPercentage = 0.0; try { cad = br.readLine(); } catch (IOException e) { e.printStackTrace(); } while (cad!=null) { if (cad.startsWith("@") == false) { st = new StringTokenizer(cad); hoped = st.nextToken(); obtained = st.nextToken(); if (obtained.equals(hoped) == true) { goods++; } instancesNumber++; totalInstances++; this.calcularConfusion(hoped,obtained); } else if (cad.startsWith("@relation")==true) { st = new StringTokenizer(cad); st.nextToken(); //@relation relation = st.nextToken(); } try { cad = br.readLine(); } catch (IOException e) { e.printStackTrace(); } } //Partial percentage partition partialPercentage = (double)((double)goods/(double)instancesNumber); partialPercentage = EducationalMethodReport.round(partialPercentage,3); partitionPercentages = partitionPercentages + n_partition + "\t" + Double.toString(partialPercentage) + "\n"; totalGoods = totalGoods + goods; break; case REGRESSION: instancesNumber = 0; String cadAux = ""; double ecmParcial = 0.0; double hopedValue = 0.0; double obtainedValue = 0.0; try { cadAux = br.readLine(); } catch (IOException e) { e.printStackTrace(); } while (cadAux!=null) { if (cadAux.startsWith("@") == false) { st = new StringTokenizer(cadAux); //row 1 ->obtained obtained = st.nextToken(); //row 2-> expected or real hoped = st.nextToken(); hopedValue = Double.valueOf(hoped); obtainedValue = Double.valueOf(obtained); double aux = (double)Math.abs((double)hopedValue - (double)obtainedValue); double partial = (double)Math.pow(aux,2); ecmParcial = ecmParcial + partial; ecmTotal = ecmTotal + partial; instancesNumber++; totalInstances++; } else if (cadAux.startsWith("@relation")==true) { st = new StringTokenizer(cadAux); st.nextToken(); //@relation relation = st.nextToken(); } try { cadAux = br.readLine(); } catch (IOException e) { e.printStackTrace(); } } double ecmParticion = 0.0; ecmParticion = (double)((double)ecmParcial/(double)instancesNumber); ecmParticion = EducationalMethodReport.round(ecmParticion,3); listECMParticion.add(Double.valueOf(ecmParticion)); cuadraticPartitionPercentages = cuadraticPartitionPercentages + n_partition + "\t" + Double.toString(ecmParticion) + "\n"; break; } try { br.close(); } catch (IOException e) { e.printStackTrace(); } }//for partitions // All partitions have finished switch (experimentType) { case CLASSIFICATION: totalPercentage = (double)((double)totalGoods / (double)totalInstances); totalPercentage = EducationalMethodReport.round(totalPercentage,3); try { if (set.equals("training")==true) { bw.write("Relation: " + relation); bw.newLine(); } else { bw.newLine(); } bw.newLine(); bw.write("Set:" + set); bw.newLine(); bw.write("Total percentage of successes:"); bw.newLine(); bw.write(Double.toString(totalPercentage)); bw.newLine(); bw.write("Percentage of successes in each partition:"); bw.newLine(); bw.write(partitionPercentages); bw.write("Confusion matrix (rows=real class;columns=obtained class):"); //bw.newLine(); for (int i=0; i<confusionMatrix.length; i++) { bw.newLine(); String filaConfusion = ""; for (int j=0; j<confusionMatrix[0].length; j++) { filaConfusion = filaConfusion + Integer.toString(confusionMatrix[i][j]) + "\t"; } bw.write(filaConfusion); } for (int i=0; i<confusionMatrix.length; i++){ Arrays.fill(confusionMatrix[i],0); } } catch (IOException e) { e.printStackTrace(); } break; case REGRESSION: ecmBest = (double)listECMParticion.get(0); for(int i=0; i<listECMParticion.size(); i++) { if((double)listECMParticion.get(i) < ecmBest) ecmBest = (double)listECMParticion.get(i); ecmAverage = (double)(ecmAverage + (double)listECMParticion.get(i)); } ecmAverage = (double)(ecmAverage / n_partition ); for(int i=0; i<listECMParticion.size(); i++) { ecmDeviation += Math.pow(((double)listECMParticion.get(i)-(double)ecmAverage), 2); } ecmDeviation /= n_partition; ecmDeviation = Math.sqrt(ecmDeviation); ecmBest = EducationalMethodReport.round(ecmBest,3); ecmAverage = EducationalMethodReport.round(ecmAverage,3); ecmDeviation = EducationalMethodReport.round(ecmDeviation,3); try { bw.newLine(); bw.write("Set:" + set); bw.newLine(); bw.write("Partial Mean Squared Error in each partition:"); bw.newLine(); bw.write(cuadraticPartitionPercentages); //bw.newLine(); "\n" In porcentajesCuadraticosParticiones bw.newLine(); bw.write("Best\tMean\tStandar Deviation:"); bw.newLine(); bw.write(Double.toString(ecmBest)+"\t"+Double.toString(ecmAverage)+"\t"+ Double.toString(ecmDeviation)); bw.newLine(); if(set.equals("test")==true) { bw.newLine(); bw.write("------ Experiments Expresions ------\n"); bw.newLine(); bw.write("Partial MSE = 1/N*(Sum[(Di-Yi)^2]), where\n" + "\"Di\" is desired result in pattern \"i\",\n" + "\"Yi\" is obtained result in pattern \"i\",\n" + "and \"N\" is number of patterns\n"); bw.newLine(); bw.write("Global MSE = sum(MSEi)/n), where\n" + "\"MSEi\" is partial MSE for partition \"i\",\n" + "and \"n\" is number of partitions\n"); bw.newLine(); bw.write("Standar Deviation = SQRT(1/n*(Sum[(GMSE-PMSEi)^2])), where\n" + "\"GMSE\" is Global MSE,\n" + "\"PMSEi\" is Partial MSE in partition \"i\",\n" + "and \"n\" is number of partitions\n"); bw.newLine(); bw.write("------ Experiments Expresions ------"); } } catch (IOException e) { e.printStackTrace(); } break; }//switch }//for training and test // All partitions have finished try { bw.write(modelContents); bw.close(); } catch (IOException e) { e.printStackTrace(); } } /** * <p> * This method calculate the classes for classification problem * This classes are used for to create confusion matrix * </p> */ private void calculateClasses() { String cad = ""; int index = 0; StringTokenizer st = null; try { fr = new FileReader(pathOutputFiles[0]); br = new BufferedReader(fr); cad = br.readLine(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } while (cad!=null) { if (cad.startsWith("@") == true) { if ( ( index = cad.indexOf("{") ) != -1 ) { cad = cad.substring(index+1, cad.length()-1); st = new StringTokenizer(cad,","); classes = new String [st.countTokens()]; int i = 0; while (st.hasMoreTokens()) { classes[i] = st.nextToken(); i++; } break; } } try { cad = br.readLine(); } catch (IOException e) { e.printStackTrace(); } } try { br.close(); } catch (IOException e) { e.printStackTrace(); } confusionMatrix = new int[classes.length][classes.length]; for(int i=0; i<classes.length; i++) for(int j=0; j<classes.length; j++) confusionMatrix[i][j] = 0; //delete spaces, tab for(int i=0; i<classes.length; i++) { StringTokenizer stAux = new StringTokenizer(classes[i]); classes[i] = stAux.nextToken(); } } /** * <p> * This method complete the confusion matrix * </p> */ private void calcularConfusion(String hoped_, String obtained_) { int posi = 0; int posj = 0; for (int i=0; i<classes.length; i++) { if(classes[i].equals(hoped_) == true) { posi = i; } if(classes[i].equals(obtained_) == true) { posj = i; } } confusionMatrix[posi][posj]++; } }