RankSearch.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 11k
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.  *    RankSearch.java
  18.  *    Copyright (C) 1999 Mark Hall
  19.  *
  20.  */
  21. package  weka.attributeSelection;
  22. import  java.io.*;
  23. import  java.util.*;
  24. import  weka.core.*;
  25. /** 
  26.  * Class for evaluating a attribute ranking (given by a specified
  27.  * evaluator) using a specified subset evaluator. <p>
  28.  *
  29.  * Valid options are: <p>
  30.  *
  31.  * -A <attribute/subset evaluator> <br>
  32.  * Specify the attribute/subset evaluator to be used for generating the 
  33.  * ranking. If a subset evaluator is specified then a forward selection
  34.  * search is used to produce a ranked list of attributes.<p>
  35.  *
  36.  * @author Mark Hall (mhall@cs.waikato.ac.nz)
  37.  * @version $Revision: 1.7 $
  38.  */
  39. public class RankSearch extends ASSearch implements OptionHandler {
  40.   /** does the data have a class */
  41.   private boolean m_hasClass;
  42.  
  43.   /** holds the class index */
  44.   private int m_classIndex;
  45.  
  46.   /** number of attributes in the data */
  47.   private int m_numAttribs;
  48.   /** the best subset found */
  49.   private BitSet m_best_group;
  50.   /** the attribute evaluator to use for generating the ranking */
  51.   private ASEvaluation m_ASEval;
  52.   /** the subset evaluator with which to evaluate the ranking */
  53.   private ASEvaluation m_SubsetEval;
  54.   /** the training instances */
  55.   private Instances m_Instances;
  56.   /** the merit of the best subset found */
  57.   private double m_bestMerit;
  58.   /** will hold the attribute ranking */
  59.   private int [] m_Ranking;
  60.   /**
  61.    * Returns a string describing this search method
  62.    * @return a description of the search method suitable for
  63.    * displaying in the explorer/experimenter gui
  64.    */
  65.   public String globalInfo() {
  66.     return "RankSearch : nn"
  67.       +"Uses an attribute/subset evaluator to rank all attributes. "
  68.       +"If a subset evaluator is specified, then a forward selection "
  69.       +"search is used to generate a ranked list. From the ranked "
  70.       +"list of attributes, subsets of increasing size are evaluated, ie. "
  71.       +"The best attribute, the best attribute plus the next best attribute, "
  72.       +"etc.... The best attribute set is reported. RankSearch is linear in "
  73.       +"the number of attributes if a simple attribute evaluator is used "
  74.       +"such as GainRatioAttributeEval.n";
  75.   }
  76.   public RankSearch () {
  77.     resetOptions();
  78.   }
  79.   /**
  80.    * Returns the tip text for this property
  81.    * @return tip text for this property suitable for
  82.    * displaying in the explorer/experimenter gui
  83.    */
  84.   public String attributeEvaluatorTipText() {
  85.     return "Attribute evaluator to use for generating a ranking.";    
  86.   }
  87.   /**
  88.    * Set the attribute evaluator to use for generating the ranking.
  89.    * @param newEvaluator the attribute evaluator to use.
  90.    */
  91.   public void setAttributeEvaluator(ASEvaluation newEvaluator) {
  92.     m_ASEval = newEvaluator;
  93.   }
  94.   /**
  95.    * Get the attribute evaluator used to generate the ranking.
  96.    * @return the evaluator used to generate the ranking.
  97.    */
  98.   public ASEvaluation getAttributeEvaluator() {
  99.     return m_ASEval;
  100.   }
  101.   /**
  102.    * Returns an enumeration describing the available options.
  103.    * @return an enumeration of all the available options.
  104.    **/
  105.   public Enumeration listOptions () {
  106.     Vector newVector = new Vector(4);
  107.     newVector.addElement(new Option("tclass name of attribute evaluator to" 
  108.        + "ntuse for ranking. Place any" 
  109.        + "ntevaluator options LAST on the" 
  110.        + "ntcommand line following a "--"." 
  111.        + "nteg. -A weka.attributeSelection."
  112.        +"GainRatioAttributeEval ... " 
  113.        + "-- -M", "A", 1, "-A <attribute evaluator>"));
  114.     if ((m_ASEval != null) && 
  115. (m_ASEval instanceof OptionHandler)) {
  116.       newVector.addElement(new Option("", "", 0, "nOptions specific to" 
  117.       + "evaluator " 
  118.       + m_ASEval.getClass().getName() 
  119.       + ":"));
  120.       Enumeration enum = ((OptionHandler)m_ASEval).listOptions();
  121.       while (enum.hasMoreElements()) {
  122.         newVector.addElement(enum.nextElement());
  123.       }
  124.     }
  125.     return newVector.elements();
  126.   }
  127.   /**
  128.    * Parses a given list of options.
  129.    *
  130.    * Valid options are:<p>
  131.    *
  132.    * -A <attribute evaluator> <br>
  133.    *
  134.    * @param options the list of options as an array of strings
  135.    * @exception Exception if an option is not supported
  136.    *
  137.    **/
  138.   public void setOptions (String[] options)
  139.     throws Exception
  140.   {
  141.     String optionString;
  142.     resetOptions();
  143.     optionString = Utils.getOption('A', options);
  144.     if (optionString.length() == 0) {
  145.       throw  new Exception("An attribute evaluator  must be specified with" 
  146.    + "-A option");
  147.     }
  148.     setAttributeEvaluator(ASEvaluation.forName(optionString, 
  149.      Utils.partitionOptions(options)));
  150.   }
  151.   /**
  152.    * Gets the current settings of WrapperSubsetEval.
  153.    *
  154.    * @return an array of strings suitable for passing to setOptions()
  155.    */
  156.   public String[] getOptions () {
  157.     String[] evaluatorOptions = new String[0];
  158.     if ((m_ASEval != null) && 
  159. (m_ASEval instanceof OptionHandler)) {
  160.       evaluatorOptions = ((OptionHandler)m_ASEval).getOptions();
  161.     }
  162.     String[] options = new String[4 + evaluatorOptions.length];
  163.     int current = 0;
  164.     if (getAttributeEvaluator() != null) {
  165.       options[current++] = "-A";
  166.       options[current++] = getAttributeEvaluator().getClass().getName();
  167.     }
  168.     options[current++] = "--";
  169.     System.arraycopy(evaluatorOptions, 0, options, current, 
  170.      evaluatorOptions.length);
  171.     current += evaluatorOptions.length;
  172.     while (current < options.length) {
  173.       options[current++] = "";
  174.     }
  175.     return  options;
  176.   }
  177.   /**
  178.    * Reset the search method.
  179.    */
  180.   protected void resetOptions () {
  181.     m_ASEval = new GainRatioAttributeEval();
  182.     m_Ranking = null;
  183.   }
  184.   /**
  185.    * Ranks attributes using the specified attribute evaluator and then
  186.    * searches the ranking using the supplied subset evaluator.
  187.    *
  188.    * @param ASEvaluator the subset evaluator to guide the search
  189.    * @param data the training instances.
  190.    * @return an array (not necessarily ordered) of selected attribute indexes
  191.    * @exception Exception if the search can't be completed
  192.    */
  193.   public int[] search (ASEvaluation ASEval, Instances data)
  194.     throws Exception {
  195.     
  196.     double best_merit = -Double.MAX_VALUE;
  197.     double temp_merit;
  198.     BitSet temp_group, best_group=null;
  199.     
  200.     if (!(ASEval instanceof SubsetEvaluator)) {
  201.       throw  new Exception(ASEval.getClass().getName() 
  202.    + " is not a " 
  203.    + "Subset evaluator!");
  204.     }
  205.     m_SubsetEval = ASEval;
  206.     m_Instances = data;
  207.     m_numAttribs = m_Instances.numAttributes();
  208.     /*    if (m_ASEval instanceof AttributeTransformer) {
  209.       throw new Exception("Can't use an attribute transformer "
  210.   +"with RankSearch");
  211.   } */
  212.     if (m_ASEval instanceof UnsupervisedAttributeEvaluator || 
  213. m_ASEval instanceof UnsupervisedSubsetEvaluator) {
  214.       m_hasClass = false;
  215.       if (!(m_SubsetEval instanceof UnsupervisedSubsetEvaluator)) {
  216. throw new Exception("Must use an unsupervised subset evaluator.");
  217.       }
  218.     }
  219.     else {
  220.       m_hasClass = true;
  221.       m_classIndex = m_Instances.classIndex();
  222.     }
  223.     if (m_ASEval instanceof AttributeEvaluator) {
  224.       // generate the attribute ranking first
  225.       Ranker ranker = new Ranker();
  226.       ((AttributeEvaluator)m_ASEval).buildEvaluator(m_Instances);
  227.       if (m_ASEval instanceof AttributeTransformer) {
  228. // get the transformed data a rebuild the subset evaluator
  229. m_Instances = ((AttributeTransformer)m_ASEval).
  230.   transformedData();
  231. ((SubsetEvaluator)m_SubsetEval).buildEvaluator(m_Instances);
  232.       }
  233.       m_Ranking = ranker.search((AttributeEvaluator)m_ASEval, m_Instances);
  234.     } else {
  235.       ForwardSelection fs = new ForwardSelection();
  236.       double [][]rankres; 
  237.       fs.setGenerateRanking(true);
  238.       ((SubsetEvaluator)m_ASEval).buildEvaluator(m_Instances);
  239.       fs.search(m_ASEval, m_Instances);
  240.       rankres = fs.rankedAttributes();
  241.       m_Ranking = new int[rankres.length];
  242.       for (int i=0;i<rankres.length;i++) {
  243. m_Ranking[i] = (int)rankres[i][0];
  244.       }
  245.     }
  246.     // now evaluate the attribute ranking
  247.     for (int i=0;i<m_Ranking.length;i++) {
  248.       temp_group = new BitSet(m_numAttribs);
  249.       for (int j=0;j<=i;j++) {
  250. temp_group.set(m_Ranking[j]);
  251.       }
  252.       temp_merit = ((SubsetEvaluator)m_SubsetEval).evaluateSubset(temp_group);
  253.       if (temp_merit > best_merit) {
  254. best_merit = temp_merit;;
  255. best_group = temp_group;
  256.       }
  257.     }
  258.     m_bestMerit = best_merit;
  259.     return attributeList(best_group);
  260.   }
  261.     
  262.   /**
  263.    * converts a BitSet into a list of attribute indexes 
  264.    * @param group the BitSet to convert
  265.    * @return an array of attribute indexes
  266.    **/
  267.   private int[] attributeList (BitSet group) {
  268.     int count = 0;
  269.     
  270.     // count how many were selected
  271.     for (int i = 0; i < m_numAttribs; i++) {
  272.       if (group.get(i)) {
  273. count++;
  274.       }
  275.     }
  276.     int[] list = new int[count];
  277.     count = 0;
  278.     for (int i = 0; i < m_numAttribs; i++) {
  279.       if (group.get(i)) {
  280. list[count++] = i;
  281.       }
  282.     }
  283.     return  list;
  284.   }
  285.    /**
  286.    * returns a description of the search as a String
  287.    * @return a description of the search
  288.    */
  289.   public String toString () {
  290.     StringBuffer text = new StringBuffer();
  291.     text.append("tRankSearch :n");
  292.     text.append("tAttribute evaluator : "
  293. + getAttributeEvaluator().getClass().getName() +" ");
  294.     if (m_ASEval instanceof OptionHandler) {
  295.       String[] evaluatorOptions = new String[0];
  296.       evaluatorOptions = ((OptionHandler)m_ASEval).getOptions();
  297.       for (int i=0;i<evaluatorOptions.length;i++) {
  298. text.append(evaluatorOptions[i]+' ');
  299.       }
  300.     }
  301.     text.append("n");
  302.     text.append("tAttribute ranking : n");
  303.     int rlength = (int)(Math.log(m_Ranking.length) / Math.log(10) + 1);
  304.     for (int i=0;i<m_Ranking.length;i++) {
  305.       text.append("t "+Utils.doubleToString((double)(m_Ranking[i]+1),
  306.      rlength,0)
  307.   +" "+m_Instances.attribute(m_Ranking[i]).name()+'n');
  308.     }
  309.     text.append("tMerit of best subset found : ");
  310.     int fieldwidth = 3;
  311.     double precision = (m_bestMerit - (int)m_bestMerit);
  312.     if (Math.abs(m_bestMerit) > 0) {
  313.       fieldwidth = (int)Math.abs((Math.log(Math.abs(m_bestMerit)) / Math.log(10)))+2;
  314.     }
  315.     if (Math.abs(precision) > 0) {
  316.       precision = Math.abs((Math.log(Math.abs(precision)) / Math.log(10)))+3;
  317.     } else {
  318.       precision = 2;
  319.     }
  320.     text.append(Utils.doubleToString(Math.abs(m_bestMerit),
  321.      fieldwidth+(int)precision,
  322.      (int)precision)+"n");
  323.     return text.toString();
  324.   }
  325. }