ClassifierSplitEvaluator.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 23k
Category:

Windows Develop

Development Platform:

Java

  1. /*
  2.  *    This program is free software; you can redistribute it and/or modify
  3.  *    it under the terms of the GNU General Public License as published by
  4.  *    the Free Software Foundation; either version 2 of the License, or
  5.  *    (at your option) any later version.
  6.  *
  7.  *    This program is distributed in the hope that it will be useful,
  8.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.  *    GNU General Public License for more details.
  11.  *
  12.  *    You should have received a copy of the GNU General Public License
  13.  *    along with this program; if not, write to the Free Software
  14.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  */
  16. /*
  17.  *    ClassifierSplitEvaluator.java
  18.  *    Copyright (C) 1999 Len Trigg
  19.  *
  20.  */
  21. package weka.experiment;
  22. import java.io.*;
  23. import java.util.*;
  24. import weka.core.*;
  25. import weka.classifiers.*;
  26. import weka.classifiers.rules.ZeroR;
  27. /**
  28.  * A SplitEvaluator that produces results for a classification scheme
  29.  * on a nominal class attribute.
  30.  *
  31.  * -W classname <br>
  32.  * Specify the full class name of the classifier to evaluate. <p>
  33.  *
  34.  * -C class index <br>
  35.  * The index of the class for which IR statistics are to
  36.  * be output. (default 1) <p>
  37.  *
  38.  * @author Len Trigg (trigg@cs.waikato.ac.nz)
  39.  * @version $Revision: 1.17 $
  40.  */
  41. public class ClassifierSplitEvaluator implements SplitEvaluator, 
  42.   OptionHandler, AdditionalMeasureProducer {
  43.   
  44.   /** The classifier used for evaluation */
  45.   protected Classifier m_Classifier = new ZeroR();
  46.   /** The names of any additional measures to look for in SplitEvaluators */
  47.   protected String [] m_AdditionalMeasures = null;
  48.   /** Array of booleans corresponding to the measures in m_AdditionalMeasures
  49.       indicating which of the AdditionalMeasures the current classifier
  50.       can produce */
  51.   protected boolean [] m_doesProduce = null;
  52.   /** The number of additional measures that need to be filled in
  53.       after taking into account column constraints imposed by the final
  54.       destination for results */
  55.   protected int m_numberAdditionalMeasures = 0;
  56.   /** Holds the statistics for the most recent application of the classifier */
  57.   protected String m_result = null;
  58.   /** The classifier options (if any) */
  59.   protected String m_ClassifierOptions = "";
  60.   /** The classifier version */
  61.   protected String m_ClassifierVersion = "";
  62.   /** The length of a key */
  63.   private static final int KEY_SIZE = 3;
  64.   /** The length of a result */
  65.   private static final int RESULT_SIZE = 24;
  66.   /** The number of IR statistics */
  67.   private static final int NUM_IR_STATISTICS = 11;
  68.   /** Class index for information retrieval statistics (default 0) */
  69.   private int m_IRclass = 0;
  70.   /**
  71.    * No args constructor.
  72.    */
  73.   public ClassifierSplitEvaluator() {
  74.     updateOptions();
  75.   }
  76.   /**
  77.    * Returns a string describing this split evaluator
  78.    * @return a description of the split evaluator suitable for
  79.    * displaying in the explorer/experimenter gui
  80.    */
  81.   public String globalInfo() {
  82.     return " A SplitEvaluator that produces results for a classification "
  83.       +"scheme on a nominal class attribute.";
  84.   }
  85.   /**
  86.    * Returns an enumeration describing the available options..
  87.    *
  88.    * @return an enumeration of all the available options.
  89.    */
  90.   public Enumeration listOptions() {
  91.     Vector newVector = new Vector(2);
  92.     newVector.addElement(new Option(
  93.      "tThe full class name of the classifier.n"
  94.       +"teg: weka.classifiers.bayes.NaiveBayes", 
  95.      "W", 1, 
  96.      "-W <class name>"));
  97.     newVector.addElement(new Option(
  98.      "tThe index of the class for which IR statisticsn" +
  99.      "tare to be output. (default 1)",
  100.      "C", 1, 
  101.      "-C <index>"));
  102.     if ((m_Classifier != null) &&
  103. (m_Classifier instanceof OptionHandler)) {
  104.       newVector.addElement(new Option(
  105.      "",
  106.      "", 0, "nOptions specific to classifier "
  107.      + m_Classifier.getClass().getName() + ":"));
  108.       Enumeration enum = ((OptionHandler)m_Classifier).listOptions();
  109.       while (enum.hasMoreElements()) {
  110. newVector.addElement(enum.nextElement());
  111.       }
  112.     }
  113.     return newVector.elements();
  114.   }
  115.   /**
  116.    * Parses a given list of options. Valid options are:<p>
  117.    *
  118.    * -W classname <br>
  119.    * Specify the full class name of the classifier to evaluate. <p>
  120.    *
  121.    * -C class index <br>
  122.    * The index of the class for which IR statistics are to
  123.    * be output. (default 1) <p>
  124.    *
  125.    * All option after -- will be passed to the classifier.
  126.    *
  127.    * @param options the list of options as an array of strings
  128.    * @exception Exception if an option is not supported
  129.    */
  130.   public void setOptions(String[] options) throws Exception {
  131.     
  132.     String cName = Utils.getOption('W', options);
  133.     if (cName.length() == 0) {
  134.       throw new Exception("A classifier must be specified with"
  135.   + " the -W option.");
  136.     }
  137.     // Do it first without options, so if an exception is thrown during
  138.     // the option setting, listOptions will contain options for the actual
  139.     // Classifier.
  140.     setClassifier(Classifier.forName(cName, null));
  141.     if (getClassifier() instanceof OptionHandler) {
  142.       ((OptionHandler) getClassifier())
  143. .setOptions(Utils.partitionOptions(options));
  144.       updateOptions();
  145.     }
  146.     String indexName = Utils.getOption('C', options);
  147.     if (indexName.length() != 0) {
  148.       m_IRclass = (new Integer(indexName)).intValue() - 1;
  149.     } else {
  150.       m_IRclass = 0;
  151.     }
  152.   }
  153.   /**
  154.    * Gets the current settings of the Classifier.
  155.    *
  156.    * @return an array of strings suitable for passing to setOptions
  157.    */
  158.   public String [] getOptions() {
  159.     String [] classifierOptions = new String [0];
  160.     if ((m_Classifier != null) && 
  161. (m_Classifier instanceof OptionHandler)) {
  162.       classifierOptions = ((OptionHandler)m_Classifier).getOptions();
  163.     }
  164.     
  165.     String [] options = new String [classifierOptions.length + 5];
  166.     int current = 0;
  167.     if (getClassifier() != null) {
  168.       options[current++] = "-W";
  169.       options[current++] = getClassifier().getClass().getName();
  170.     }
  171.     options[current++] = "-C"; 
  172.     options[current++] = "" + (m_IRclass + 1);
  173.     options[current++] = "--";
  174.     System.arraycopy(classifierOptions, 0, options, current, 
  175.      classifierOptions.length);
  176.     current += classifierOptions.length;
  177.     while (current < options.length) {
  178.       options[current++] = "";
  179.     }
  180.     return options;
  181.   }
  182.   /**
  183.    * Set a list of method names for additional measures to look for
  184.    * in Classifiers. This could contain many measures (of which only a
  185.    * subset may be produceable by the current Classifier) if an experiment
  186.    * is the type that iterates over a set of properties.
  187.    * @param additionalMeasures a list of method names
  188.    */
  189.   public void setAdditionalMeasures(String [] additionalMeasures) {
  190.     System.err.println("ClassifierSplitEvaluator: setting additional measures");
  191.       m_AdditionalMeasures = additionalMeasures;
  192.     
  193.     // determine which (if any) of the additional measures this classifier
  194.     // can produce
  195.     if (m_AdditionalMeasures != null && m_AdditionalMeasures.length > 0) {
  196.       m_doesProduce = new boolean [m_AdditionalMeasures.length];
  197.       if (m_Classifier instanceof AdditionalMeasureProducer) {
  198. Enumeration en = ((AdditionalMeasureProducer)m_Classifier).
  199.   enumerateMeasures();
  200. while (en.hasMoreElements()) {
  201.   String mname = (String)en.nextElement();
  202.   for (int j=0;j<m_AdditionalMeasures.length;j++) {
  203.     if (mname.compareTo(m_AdditionalMeasures[j]) == 0) {
  204.       m_doesProduce[j] = true;
  205.     }
  206.   }
  207. }
  208.       }
  209.     } else {
  210.       m_doesProduce = null;
  211.     }
  212.   }
  213.   /**
  214.    * Returns an enumeration of any additional measure names that might be
  215.    * in the classifier
  216.    * @return an enumeration of the measure names
  217.    */
  218.   public Enumeration enumerateMeasures() {
  219.     Vector newVector = new Vector();
  220.     if (m_Classifier instanceof AdditionalMeasureProducer) {
  221.       Enumeration en = ((AdditionalMeasureProducer)m_Classifier).
  222. enumerateMeasures();
  223.       while (en.hasMoreElements()) {
  224. String mname = (String)en.nextElement();
  225. newVector.addElement(mname);
  226.       }
  227.     }
  228.     return newVector.elements();
  229.   }
  230.   
  231.   /**
  232.    * Returns the value of the named measure
  233.    * @param measureName the name of the measure to query for its value
  234.    * @return the value of the named measure
  235.    * @exception IllegalArgumentException if the named measure is not supported
  236.    */
  237.   public double getMeasure(String additionalMeasureName) {
  238.     if (m_Classifier instanceof AdditionalMeasureProducer) {
  239.       return ((AdditionalMeasureProducer)m_Classifier).
  240. getMeasure(additionalMeasureName);
  241.     } else {
  242.       throw new IllegalArgumentException("ClassifierSplitEvaluator: "
  243.   +"Can't return value for : "+additionalMeasureName
  244.   +". "+m_Classifier.getClass().getName()+" "
  245.   +"is not an AdditionalMeasureProducer");
  246.     }
  247.   }
  248.   /**
  249.    * Gets the data types of each of the key columns produced for a single run.
  250.    * The number of key fields must be constant
  251.    * for a given SplitEvaluator.
  252.    *
  253.    * @return an array containing objects of the type of each key column. The 
  254.    * objects should be Strings, or Doubles.
  255.    */
  256.   public Object [] getKeyTypes() {
  257.     Object [] keyTypes = new Object[KEY_SIZE];
  258.     keyTypes[0] = "";
  259.     keyTypes[1] = "";
  260.     keyTypes[2] = "";
  261.     return keyTypes;
  262.   }
  263.   /**
  264.    * Gets the names of each of the key columns produced for a single run.
  265.    * The number of key fields must be constant
  266.    * for a given SplitEvaluator.
  267.    *
  268.    * @return an array containing the name of each key column
  269.    */
  270.   public String [] getKeyNames() {
  271.     String [] keyNames = new String[KEY_SIZE];
  272.     keyNames[0] = "Scheme";
  273.     keyNames[1] = "Scheme_options";
  274.     keyNames[2] = "Scheme_version_ID";
  275.     return keyNames;
  276.   }
  277.   /**
  278.    * Gets the key describing the current SplitEvaluator. For example
  279.    * This may contain the name of the classifier used for classifier
  280.    * predictive evaluation. The number of key fields must be constant
  281.    * for a given SplitEvaluator.
  282.    *
  283.    * @return an array of objects containing the key.
  284.    */
  285.   public Object [] getKey(){
  286.     Object [] key = new Object[KEY_SIZE];
  287.     key[0] = m_Classifier.getClass().getName();
  288.     key[1] = m_ClassifierOptions;
  289.     key[2] = m_ClassifierVersion;
  290.     return key;
  291.   }
  292.   /**
  293.    * Gets the data types of each of the result columns produced for a 
  294.    * single run. The number of result fields must be constant
  295.    * for a given SplitEvaluator.
  296.    *
  297.    * @return an array containing objects of the type of each result column. 
  298.    * The objects should be Strings, or Doubles.
  299.    */
  300.   public Object [] getResultTypes() {
  301.     int addm = (m_AdditionalMeasures != null) 
  302.       ? m_AdditionalMeasures.length 
  303.       : 0;
  304.     int overall_length = RESULT_SIZE+addm;
  305.     overall_length += NUM_IR_STATISTICS;
  306.     Object [] resultTypes = new Object[overall_length];
  307.     Double doub = new Double(0);
  308.     int current = 0;
  309.     resultTypes[current++] = doub;
  310.     resultTypes[current++] = doub;
  311.     resultTypes[current++] = doub;
  312.     resultTypes[current++] = doub;
  313.     resultTypes[current++] = doub;
  314.     resultTypes[current++] = doub;
  315.     resultTypes[current++] = doub;
  316.     resultTypes[current++] = doub;
  317.     resultTypes[current++] = doub;
  318.     resultTypes[current++] = doub;
  319.     resultTypes[current++] = doub;
  320.     resultTypes[current++] = doub;
  321.     resultTypes[current++] = doub;
  322.     resultTypes[current++] = doub;
  323.     resultTypes[current++] = doub;
  324.     resultTypes[current++] = doub;
  325.     resultTypes[current++] = doub;
  326.     resultTypes[current++] = doub;
  327.     resultTypes[current++] = doub;
  328.     resultTypes[current++] = doub;
  329.     resultTypes[current++] = doub;
  330.     // IR stats
  331.     resultTypes[current++] = doub;
  332.     resultTypes[current++] = doub;
  333.     resultTypes[current++] = doub;
  334.     resultTypes[current++] = doub;
  335.     resultTypes[current++] = doub;
  336.     resultTypes[current++] = doub;
  337.     resultTypes[current++] = doub;
  338.     resultTypes[current++] = doub;
  339.     resultTypes[current++] = doub;
  340.     resultTypes[current++] = doub;
  341.     resultTypes[current++] = doub;
  342.     // Timing stats
  343.     resultTypes[current++] = doub;
  344.     resultTypes[current++] = doub;
  345.     resultTypes[current++] = "";
  346.     // add any additional measures
  347.     for (int i=0;i<addm;i++) {
  348.       resultTypes[current++] = doub;
  349.     }
  350.     if (current != overall_length) {
  351.       throw new Error("ResultTypes didn't fit RESULT_SIZE");
  352.     }
  353.     return resultTypes;
  354.   }
  355.   /**
  356.    * Gets the names of each of the result columns produced for a single run.
  357.    * The number of result fields must be constant
  358.    * for a given SplitEvaluator.
  359.    *
  360.    * @return an array containing the name of each result column
  361.    */
  362.   public String [] getResultNames() {
  363.     int addm = (m_AdditionalMeasures != null) 
  364.       ? m_AdditionalMeasures.length 
  365.       : 0;
  366.     int overall_length = RESULT_SIZE+addm;
  367.     overall_length += NUM_IR_STATISTICS;
  368.     String [] resultNames = new String[overall_length];
  369.     int current = 0;
  370.     resultNames[current++] = "Number_of_instances";
  371.     // Basic performance stats - right vs wrong
  372.     resultNames[current++] = "Number_correct";
  373.     resultNames[current++] = "Number_incorrect";
  374.     resultNames[current++] = "Number_unclassified";
  375.     resultNames[current++] = "Percent_correct";
  376.     resultNames[current++] = "Percent_incorrect";
  377.     resultNames[current++] = "Percent_unclassified";
  378.     resultNames[current++] = "Kappa_statistic";
  379.     // Sensitive stats - certainty of predictions
  380.     resultNames[current++] = "Mean_absolute_error";
  381.     resultNames[current++] = "Root_mean_squared_error";
  382.     resultNames[current++] = "Relative_absolute_error";
  383.     resultNames[current++] = "Root_relative_squared_error";
  384.     // SF stats
  385.     resultNames[current++] = "SF_prior_entropy";
  386.     resultNames[current++] = "SF_scheme_entropy";
  387.     resultNames[current++] = "SF_entropy_gain";
  388.     resultNames[current++] = "SF_mean_prior_entropy";
  389.     resultNames[current++] = "SF_mean_scheme_entropy";
  390.     resultNames[current++] = "SF_mean_entropy_gain";
  391.     // K&B stats
  392.     resultNames[current++] = "KB_information";
  393.     resultNames[current++] = "KB_mean_information";
  394.     resultNames[current++] = "KB_relative_information";
  395.     // IR stats
  396.     resultNames[current++] = "True_positive_rate";
  397.     resultNames[current++] = "Num_true_positives";
  398.     resultNames[current++] = "False_positive_rate";
  399.     resultNames[current++] = "Num_false_positives";
  400.     resultNames[current++] = "True_negative_rate";
  401.     resultNames[current++] = "Num_true_negatives";
  402.     resultNames[current++] = "False_negative_rate";
  403.     resultNames[current++] = "Num_false_negatives";
  404.     resultNames[current++] = "IR_precision";
  405.     resultNames[current++] = "IR_recall";
  406.     resultNames[current++] = "F_measure";
  407.     // Timing stats
  408.     resultNames[current++] = "Time_training";
  409.     resultNames[current++] = "Time_testing";
  410.     // Classifier defined extras
  411.     resultNames[current++] = "Summary";
  412.     // add any additional measures
  413.     for (int i=0;i<addm;i++) {
  414.       resultNames[current++] = m_AdditionalMeasures[i];
  415.     }
  416.     if (current != overall_length) {
  417.       throw new Error("ResultNames didn't fit RESULT_SIZE");
  418.     }
  419.     return resultNames;
  420.   }
  421.   /**
  422.    * Gets the results for the supplied train and test datasets.
  423.    *
  424.    * @param train the training Instances.
  425.    * @param test the testing Instances.
  426.    * @return the results stored in an array. The objects stored in
  427.    * the array may be Strings, Doubles, or null (for the missing value).
  428.    * @exception Exception if a problem occurs while getting the results
  429.    */
  430.   public Object [] getResult(Instances train, Instances test) 
  431.     throws Exception {
  432.     
  433.     if (train.classAttribute().type() != Attribute.NOMINAL) {
  434.       throw new Exception("Class attribute is not nominal!");
  435.     }
  436.     if (m_Classifier == null) {
  437.       throw new Exception("No classifier has been specified");
  438.     }
  439.     int addm = (m_AdditionalMeasures != null) 
  440.       ? m_AdditionalMeasures.length 
  441.       : 0;
  442.     int overall_length = RESULT_SIZE+addm;
  443.     overall_length += NUM_IR_STATISTICS;
  444.     Object [] result = new Object[overall_length];
  445.     Evaluation eval = new Evaluation(train);
  446.     long trainTimeStart = System.currentTimeMillis();
  447.     m_Classifier.buildClassifier(train);
  448.     long trainTimeElapsed = System.currentTimeMillis() - trainTimeStart;
  449.     long testTimeStart = System.currentTimeMillis();
  450.     eval.evaluateModel(m_Classifier, test);
  451.     long testTimeElapsed = System.currentTimeMillis() - testTimeStart;
  452.     m_result = eval.toSummaryString();
  453.     // The results stored are all per instance -- can be multiplied by the
  454.     // number of instances to get absolute numbers
  455.     int current = 0;
  456.     result[current++] = new Double(eval.numInstances());
  457.     result[current++] = new Double(eval.correct());
  458.     result[current++] = new Double(eval.incorrect());
  459.     result[current++] = new Double(eval.unclassified());
  460.     result[current++] = new Double(eval.pctCorrect());
  461.     result[current++] = new Double(eval.pctIncorrect());
  462.     result[current++] = new Double(eval.pctUnclassified());
  463.     result[current++] = new Double(eval.kappa());
  464.     result[current++] = new Double(eval.meanAbsoluteError());
  465.     result[current++] = new Double(eval.rootMeanSquaredError());
  466.     result[current++] = new Double(eval.relativeAbsoluteError());
  467.     result[current++] = new Double(eval.rootRelativeSquaredError());
  468.     result[current++] = new Double(eval.SFPriorEntropy());
  469.     result[current++] = new Double(eval.SFSchemeEntropy());
  470.     result[current++] = new Double(eval.SFEntropyGain());
  471.     result[current++] = new Double(eval.SFMeanPriorEntropy());
  472.     result[current++] = new Double(eval.SFMeanSchemeEntropy());
  473.     result[current++] = new Double(eval.SFMeanEntropyGain());
  474.     // K&B stats
  475.     result[current++] = new Double(eval.KBInformation());
  476.     result[current++] = new Double(eval.KBMeanInformation());
  477.     result[current++] = new Double(eval.KBRelativeInformation());
  478.     // IR stats
  479.     result[current++] = new Double(eval.truePositiveRate(m_IRclass));
  480.     result[current++] = new Double(eval.numTruePositives(m_IRclass));
  481.     result[current++] = new Double(eval.falsePositiveRate(m_IRclass));
  482.     result[current++] = new Double(eval.numFalsePositives(m_IRclass));
  483.     result[current++] = new Double(eval.trueNegativeRate(m_IRclass));
  484.     result[current++] = new Double(eval.numTrueNegatives(m_IRclass));
  485.     result[current++] = new Double(eval.falseNegativeRate(m_IRclass));
  486.     result[current++] = new Double(eval.numFalseNegatives(m_IRclass));
  487.     result[current++] = new Double(eval.precision(m_IRclass));
  488.     result[current++] = new Double(eval.recall(m_IRclass));
  489.     result[current++] = new Double(eval.fMeasure(m_IRclass));
  490.     // Timing stats
  491.     result[current++] = new Double(trainTimeElapsed / 1000.0);
  492.     result[current++] = new Double(testTimeElapsed / 1000.0);
  493.     if (m_Classifier instanceof Summarizable) {
  494.       result[current++] = ((Summarizable)m_Classifier).toSummaryString();
  495.     } else {
  496.       result[current++] = null;
  497.     }
  498.     for (int i=0;i<addm;i++) {
  499.       if (m_doesProduce[i]) {
  500. try {
  501.   double dv = ((AdditionalMeasureProducer)m_Classifier).
  502.     getMeasure(m_AdditionalMeasures[i]);
  503.   Double value = new Double(dv);
  504.   result[current++] = value;
  505. } catch (Exception ex) {
  506.   System.err.println(ex);
  507. }
  508.       } else {
  509. result[current++] = null;
  510.       }
  511.     }
  512.     if (current != overall_length) {
  513.       throw new Error("Results didn't fit RESULT_SIZE");
  514.     }
  515.     return result;
  516.   }
  517.   /**
  518.    * Returns the tip text for this property
  519.    * @return tip text for this property suitable for
  520.    * displaying in the explorer/experimenter gui
  521.    */
  522.   public String classifierTipText() {
  523.     return "The classifier to use.";
  524.   }
  525.   /**
  526.    * Get the value of Classifier.
  527.    *
  528.    * @return Value of Classifier.
  529.    */
  530.   public Classifier getClassifier() {
  531.     
  532.     return m_Classifier;
  533.   }
  534.   
  535.   /**
  536.    * Sets the classifier.
  537.    *
  538.    * @param newClassifier the new classifier to use.
  539.    */
  540.   public void setClassifier(Classifier newClassifier) {
  541.     
  542.     m_Classifier = newClassifier;
  543.     updateOptions();
  544.     
  545.     System.err.println("ClassifierSplitEvaluator: In set classifier");
  546.   }
  547.   
  548.   /**
  549.    * Get the value of ClassForIRStatistics.
  550.    * @return Value of ClassForIRStatistics.
  551.    */
  552.   public int getClassForIRStatistics() {
  553.     
  554.     return m_IRclass;
  555.   }
  556.   
  557.   /**
  558.    * Set the value of ClassForIRStatistics.
  559.    * @param v  Value to assign to ClassForIRStatistics.
  560.    */
  561.   public void setClassForIRStatistics(int v) {
  562.     
  563.     m_IRclass = v;
  564.   }
  565.   
  566.   /**
  567.    * Updates the options that the current classifier is using.
  568.    */
  569.   protected void updateOptions() {
  570.     
  571.     if (m_Classifier instanceof OptionHandler) {
  572.       m_ClassifierOptions = Utils.joinOptions(((OptionHandler)m_Classifier)
  573.       .getOptions());
  574.     } else {
  575.       m_ClassifierOptions = "";
  576.     }
  577.     if (m_Classifier instanceof Serializable) {
  578.       ObjectStreamClass obs = ObjectStreamClass.lookup(m_Classifier
  579.        .getClass());
  580.       m_ClassifierVersion = "" + obs.getSerialVersionUID();
  581.     } else {
  582.       m_ClassifierVersion = "";
  583.     }
  584.   }
  585.   /**
  586.    * Set the Classifier to use, given it's class name. A new classifier will be
  587.    * instantiated.
  588.    *
  589.    * @param newClassifier the Classifier class name.
  590.    * @exception Exception if the class name is invalid.
  591.    */
  592.   public void setClassifierName(String newClassifierName) throws Exception {
  593.     try {
  594.       setClassifier((Classifier)Class.forName(newClassifierName)
  595.     .newInstance());
  596.     } catch (Exception ex) {
  597.       throw new Exception("Can't find Classifier with class name: "
  598.   + newClassifierName);
  599.     }
  600.   }
  601.   /**
  602.    * Gets the raw output from the classifier
  603.    * @return the raw output from the classifier
  604.    */
  605.   public String getRawResultOutput() {
  606.     StringBuffer result = new StringBuffer();
  607.     if (m_Classifier == null) {
  608.       return "<null> classifier";
  609.     }
  610.     result.append(toString());
  611.     result.append("Classifier model: n"+m_Classifier.toString()+'n');
  612.     // append the performance statistics
  613.     if (m_result != null) {
  614.       result.append(m_result);
  615.       
  616.       if (m_doesProduce != null) {
  617. for (int i=0;i<m_doesProduce.length;i++) {
  618.   if (m_doesProduce[i]) {
  619.     try {
  620.       double dv = ((AdditionalMeasureProducer)m_Classifier).
  621. getMeasure(m_AdditionalMeasures[i]);
  622.       Double value = new Double(dv);
  623.       
  624.       result.append(m_AdditionalMeasures[i]+" : "+value+'n');
  625.     } catch (Exception ex) {
  626.       System.err.println(ex);
  627.     }
  628.   } 
  629. }
  630.       }
  631.     }
  632.     return result.toString();
  633.   }
  634.   /**
  635.    * Returns a text description of the split evaluator.
  636.    *
  637.    * @return a text description of the split evaluator.
  638.    */
  639.   public String toString() {
  640.     String result = "ClassifierSplitEvaluator: ";
  641.     if (m_Classifier == null) {
  642.       return result + "<null> classifier";
  643.     }
  644.     return result + m_Classifier.getClass().getName() + " " 
  645.       + m_ClassifierOptions + "(version " + m_ClassifierVersion + ")";
  646.   }
  647. } // ClassifierSplitEvaluator