ClassifierPerformanceEvaluator.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 7k
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.  *    ClassifierPerformanceEvaluator.java
  18.  *    Copyright (C) 2002 Mark Hall
  19.  *
  20.  */
  21. package weka.gui.beans;
  22. import weka.classifiers.Classifier;
  23. import weka.classifiers.Evaluation;
  24. import weka.core.Instances;
  25. import weka.gui.Logger;
  26. import java.io.Serializable;
  27. import java.util.Vector;
  28. import java.util.Enumeration;
  29. import javax.swing.JPanel;
  30. import javax.swing.JLabel;
  31. import javax.swing.JTextArea;
  32. import javax.swing.ImageIcon;
  33. import javax.swing.SwingConstants;
  34. import javax.swing.JFrame;
  35. import javax.swing.BorderFactory;
  36. import java.awt.*;
  37. import javax.swing.JScrollPane;
  38. /**
  39.  * A bean that evaluates the performance of batch trained classifiers
  40.  *
  41.  * @author <a href="mailto:mhall@cs.waikato.ac.nz">Mark Hall</a>
  42.  * @version $Revision: 1.1 $
  43.  */
  44. public class ClassifierPerformanceEvaluator 
  45.   extends AbstractEvaluator
  46.   implements BatchClassifierListener, 
  47.      Serializable, UserRequestAcceptor, EventConstraints {
  48.   /**
  49.    * Evaluation object used for evaluating a classifier
  50.    */
  51.   private transient Evaluation m_eval;
  52.   /**
  53.    * Holds the classifier to be evaluated
  54.    */
  55.   private transient Classifier m_classifier;
  56.   private transient Thread m_evaluateThread = null;
  57.   
  58.   private Vector m_listeners = new Vector();
  59.   public ClassifierPerformanceEvaluator() {
  60.     m_visual.loadIcons(BeanVisual.ICON_PATH
  61.        +"ClassifierPerformanceEvaluator.gif",
  62.        BeanVisual.ICON_PATH
  63.        +"ClassifierPerformanceEvaluator_animated.gif");
  64.     m_visual.setText("ClassifierPerformanceEvaluator");
  65.   }
  66.   
  67.   /**
  68.    * Accept a classifier to be evaluated
  69.    *
  70.    * @param ce a <code>BatchClassifierEvent</code> value
  71.    */
  72.   public void acceptClassifier(final BatchClassifierEvent ce) {
  73.     try {
  74.       if (m_evaluateThread == null) {
  75. m_evaluateThread = new Thread() {
  76.     public void run() {
  77.       final String oldText = m_visual.getText();
  78.       try {
  79. if (ce.getSetNumber() == 1 || 
  80.     ce.getClassifier() != m_classifier) {
  81.   m_eval = new Evaluation(ce.getTestSet());
  82.   m_classifier = ce.getClassifier();
  83. }
  84. if (ce.getSetNumber() <= ce.getMaxSetNumber()) {
  85.   m_visual.setText("Evaluating ("+ce.getSetNumber()+")...");
  86.   if (m_logger != null) {
  87.     m_logger.statusMessage("ClassifierPerformaceEvaluator : "
  88.    +"evaluating ("+ce.getSetNumber()
  89.    +")...");
  90.   }
  91.   m_visual.setAnimated();
  92.   m_eval.evaluateModel(ce.getClassifier(), ce.getTestSet());
  93. }
  94. if (ce.getSetNumber() == ce.getMaxSetNumber()) {
  95.   System.err.println(m_eval.toSummaryString());
  96.   // m_resultsString.append(m_eval.toSummaryString());
  97.   // m_outText.setText(m_resultsString.toString());
  98.   String textTitle = m_classifier.getClass().getName();
  99.   textTitle = 
  100.     textTitle.substring(textTitle.lastIndexOf('.')+1,
  101. textTitle.length());
  102.   TextEvent te = 
  103.     new TextEvent(ClassifierPerformanceEvaluator.this, 
  104.   m_eval.toSummaryString(),
  105.   textTitle);
  106.   notifyTextListeners(te);
  107.   if (m_logger != null) {
  108.     m_logger.statusMessage("Done.");
  109.   }
  110. }
  111.       } catch (Exception ex) {
  112. ex.printStackTrace();
  113.       } finally {
  114. m_visual.setText(oldText);
  115. m_visual.setStatic();
  116. m_evaluateThread = null;
  117. if (isInterrupted()) {
  118.   if (m_logger != null) {
  119.     m_logger.logMessage("Evaluation interrupted!");
  120.     m_logger.statusMessage("OK");
  121.   }
  122. }
  123. block(false);
  124.       }
  125.     }
  126.   };
  127. m_evaluateThread.setPriority(Thread.MIN_PRIORITY);
  128. m_evaluateThread.start();
  129. // make sure the thread is still running before we block
  130. // if (m_evaluateThread.isAlive()) {
  131. block(true);
  132.   // }
  133. m_evaluateThread = null;
  134.       }
  135.     }  catch (Exception ex) {
  136.       ex.printStackTrace();
  137.     }
  138.   }
  139.   /**
  140.    * Try and stop any action
  141.    */
  142.   public void stop() {
  143.     // tell the listenee (upstream bean) to stop
  144.     if (m_listenee instanceof BeanCommon) {
  145.       System.err.println("Listener is BeanCommon");
  146.       ((BeanCommon)m_listenee).stop();
  147.     }
  148.     // stop the evaluate thread
  149.     if (m_evaluateThread != null) {
  150.       m_evaluateThread.interrupt();
  151.       m_evaluateThread.stop();
  152.     }
  153.   }
  154.   
  155.   /**
  156.    * Function used to stop code that calls acceptClassifier. This is 
  157.    * needed as classifier evaluation is performed inside a separate
  158.    * thread of execution.
  159.    *
  160.    * @param tf a <code>boolean</code> value
  161.    */
  162.   private synchronized void block(boolean tf) {
  163.     if (tf) {
  164.       try {
  165. // only block if thread is still doing something useful!
  166. if (m_evaluateThread != null && m_evaluateThread.isAlive()) {
  167.   wait();
  168. }
  169.       } catch (InterruptedException ex) {
  170.       }
  171.     } else {
  172.       notifyAll();
  173.     }
  174.   }
  175.   /**
  176.    * Return an enumeration of user activated requests for this bean
  177.    *
  178.    * @return an <code>Enumeration</code> value
  179.    */
  180.   public Enumeration enumerateRequests() {
  181.     Vector newVector = new Vector(0);
  182.     if (m_evaluateThread != null) {
  183.       newVector.addElement("Stop");
  184.     }
  185.     return newVector.elements();
  186.   }
  187.   /**
  188.    * Perform the named request
  189.    *
  190.    * @param request the request to perform
  191.    * @exception IllegalArgumentException if an error occurs
  192.    */
  193.   public void performRequest(String request) throws IllegalArgumentException {
  194.     if (request.compareTo("Stop") == 0) {
  195.       stop();
  196.     } else {
  197.       throw new 
  198. IllegalArgumentException(request
  199.     + " not supported (ClassifierPerformanceEvaluator)");
  200.     }
  201.   }
  202.   /**
  203.    * Add a text listener
  204.    *
  205.    * @param cl a <code>TextListener</code> value
  206.    */
  207.   public synchronized void addTextListener(TextListener cl) {
  208.     m_listeners.addElement(cl);
  209.   }
  210.   /**
  211.    * Remove a text listener
  212.    *
  213.    * @param cl a <code>TextListener</code> value
  214.    */
  215.   public synchronized void removeTextListener(TextListener cl) {
  216.     m_listeners.remove(cl);
  217.   }
  218.   /**
  219.    * Notify all text listeners of a TextEvent
  220.    *
  221.    * @param te a <code>TextEvent</code> value
  222.    */
  223.   private void notifyTextListeners(TextEvent te) {
  224.     Vector l;
  225.     synchronized (this) {
  226.       l = (Vector)m_listeners.clone();
  227.     }
  228.     if (l.size() > 0) {
  229.       for(int i = 0; i < l.size(); i++) {
  230. // System.err.println("Notifying text listeners "
  231. //    +"(ClassifierPerformanceEvaluator)");
  232. ((TextListener)l.elementAt(i)).acceptText(te);
  233.       }
  234.     }
  235.   }
  236.   /**
  237.    * Returns true, if at the current time, the named event could
  238.    * be generated. Assumes that supplied event names are names of
  239.    * events that could be generated by this bean.
  240.    *
  241.    * @param eventName the name of the event in question
  242.    * @return true if the named event could be generated at this point in
  243.    * time
  244.    */
  245.   public boolean eventGeneratable(String eventName) {
  246.     if (m_listenee == null) {
  247.       return false;
  248.     }
  249.     if (m_listenee instanceof EventConstraints) {
  250.       if (!((EventConstraints)m_listenee).eventGeneratable("classifier")) {
  251. return false;
  252.       }
  253.     }
  254.     return true;
  255.   }
  256. }