AttributeSelectionFilter.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 12k
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.  *    AttributeSelectionFilter.java
  18.  *    Copyright (C) 1999 Mark Hall
  19.  *
  20.  */
  21. package weka.filters;
  22. import java.io.*;
  23. import java.util.*;
  24. import weka.core.*;
  25. import weka.attributeSelection.*;
  26. /** 
  27.  * Filter for doing attribute selection.<p>
  28.  *
  29.  * Valid options are:<p>
  30.  *
  31.  * -S <"Name of search class [search options]"> <br>
  32.  * Set search method for subset evaluators. <br>
  33.  * eg. -S "weka.attributeSelection.BestFirst -S 8" <p>
  34.  *
  35.  * -E <"Name of attribute/subset evaluation class [evaluator options]"> <br>
  36.  * Set the attribute/subset evaluator. <br>
  37.  * eg. -E "weka.attributeSelection.CfsSubsetEval -L" <p>
  38.  *
  39.  * @author Mark Hall (mhall@cs.waikato.ac.nz)
  40.  * @version $Revision: 1.19 $
  41.  */
  42. public class AttributeSelectionFilter extends Filter implements OptionHandler {
  43.   /** the attribute selection evaluation object */
  44.   private AttributeSelection m_trainSelector;
  45.   /** the attribute evaluator to use */
  46.   private ASEvaluation m_ASEvaluator;
  47.   /** the search method if any */
  48.   private ASSearch m_ASSearch;
  49.   /** holds a copy of the full set of valid  options passed to the filter */
  50.   private String [] m_FilterOptions;
  51.   /** holds the selected attributes  */
  52.   private int [] m_SelectedAttributes;
  53.   /**
  54.    * Constructor
  55.    */
  56.   public AttributeSelectionFilter () {
  57.     
  58.     resetOptions();
  59.   }
  60.   /**
  61.    * Returns an enumeration describing the available options
  62.    * @return an enumeration of all the available options
  63.    */
  64.   public Enumeration listOptions() {
  65.     
  66.     Vector newVector = new Vector(6);
  67.     newVector.addElement(new Option("tSets search method for subset "
  68.     + "evaluators.", "S", 1,
  69.     "-S <"Name of search class"
  70.     + " [search options]">"));
  71.     newVector.addElement(new Option("tSets attribute/subset evaluator.",
  72.     "E", 1,
  73.     "-E <"Name of attribute/subset "
  74.     + "evaluation class [evaluator "
  75.     + "options]">"));
  76.     
  77.     if ((m_ASEvaluator != null) && (m_ASEvaluator instanceof OptionHandler)) {
  78.       Enumeration enum = ((OptionHandler)m_ASEvaluator).listOptions();
  79.       
  80.       newVector.addElement(new Option("", "", 0, "nOptions specific to "
  81.    + "evaluator " + m_ASEvaluator.getClass().getName() + ":"));
  82.       while (enum.hasMoreElements()) {
  83. newVector.addElement((Option)enum.nextElement());
  84.       }
  85.     }
  86.   
  87.     if ((m_ASSearch != null) && (m_ASSearch instanceof OptionHandler)) {
  88.       Enumeration enum = ((OptionHandler)m_ASSearch).listOptions();
  89.     
  90.       newVector.addElement(new Option("", "", 0, "nOptions specific to "
  91.       + "search " + m_ASSearch.getClass().getName() + ":"));
  92.       while (enum.hasMoreElements()) {
  93. newVector.addElement((Option)enum.nextElement());
  94.       }
  95.     }
  96.     return newVector.elements();
  97.   }
  98.   /**
  99.    * Parses a given list of options. Valid options are:<p>
  100.    *
  101.    * -S <"Name of search class [search options]"> <br>
  102.    * Set search method for subset evaluators. <br>
  103.    * eg. -S "weka.attributeSelection.BestFirst -S 8" <p>
  104.    *
  105.    * -E <"Name of attribute/subset evaluation class [evaluator options]"> <br>
  106.    * Set the attribute/subset evaluator. <br>
  107.    * eg. -E "weka.attributeSelection.CfsSubsetEval -L" <p>
  108.    *
  109.    * @param options the list of options as an array of strings
  110.    * @exception Exception if an option is not supported
  111.    */
  112.   public void setOptions(String[] options) throws Exception {
  113.     
  114.     String optionString;
  115.     resetOptions();
  116.     if (Utils.getFlag('X',options)) {
  117. throw new Exception("Cross validation is not a valid option"
  118.     + " when using attribute selection as a Filter.");
  119.     }
  120.     optionString = Utils.getOption('E',options);
  121.     if (optionString.length() != 0) {
  122.       optionString = optionString.trim();
  123.       // split a quoted evaluator name from its options (if any)
  124.       int breakLoc = optionString.indexOf(' ');
  125.       String evalClassName = optionString;
  126.       String evalOptionsString = "";
  127.       String [] evalOptions=null;
  128.       if (breakLoc != -1) {
  129. evalClassName = optionString.substring(0, breakLoc);
  130. evalOptionsString = optionString.substring(breakLoc).trim();
  131. evalOptions = Utils.splitOptions(evalOptionsString);
  132.       }
  133.       setEvaluator(ASEvaluation.forName(evalClassName, evalOptions));
  134.     }
  135.     if (m_ASEvaluator instanceof AttributeEvaluator) {
  136.       setSearch(new Ranker());
  137.     }
  138.     optionString = Utils.getOption('S',options);
  139.     if (optionString.length() != 0) {
  140.       optionString = optionString.trim();
  141.       int breakLoc = optionString.indexOf(' ');
  142.       String SearchClassName = optionString;
  143.       String SearchOptionsString = "";
  144.       String [] SearchOptions=null;
  145.       if (breakLoc != -1) {
  146. SearchClassName = optionString.substring(0, breakLoc);
  147. SearchOptionsString = optionString.substring(breakLoc).trim();
  148. SearchOptions = Utils.splitOptions(SearchOptionsString);
  149.       }
  150.       setSearch(ASSearch.forName(SearchClassName, SearchOptions));
  151.     }
  152.     Utils.checkForRemainingOptions(options);
  153.   }
  154.   /**
  155.    * Gets the current settings for the attribute selection (search, evaluator)
  156.    * etc.
  157.    *
  158.    * @return an array of strings suitable for passing to setOptions()
  159.    */
  160.   public String [] getOptions() {
  161.     String [] EvaluatorOptions = new String[0];
  162.     String [] SearchOptions = new String[0];
  163.     int current = 0;
  164.     if (m_ASEvaluator instanceof OptionHandler) {
  165.       EvaluatorOptions = ((OptionHandler)m_ASEvaluator).getOptions();
  166.     }
  167.     if (m_ASSearch instanceof OptionHandler) {
  168.       SearchOptions = ((OptionHandler)m_ASSearch).getOptions();
  169.     }
  170.     String [] setOptions = new String [10];
  171.     setOptions[current++]="-E";
  172.     setOptions[current++]= getEvaluator().getClass().getName()
  173.       +" "+Utils.joinOptions(EvaluatorOptions);
  174.     setOptions[current++]="-S";
  175.     setOptions[current++]=getSearch().getClass().getName() 
  176.       + " "+Utils.joinOptions(SearchOptions);
  177.     while (current < setOptions.length) {
  178.       setOptions[current++] = "";
  179.     }
  180.     
  181.     return setOptions;
  182.   }
  183.   /**
  184.    * set a string holding the name of a attribute/subset evaluator
  185.    */
  186.   public void setEvaluator(ASEvaluation evaluator) {
  187.     m_ASEvaluator = evaluator;
  188.   }
  189.   /**
  190.    * Set as string holding the name of a search class
  191.    */
  192.   public void setSearch(ASSearch search) {
  193.     m_ASSearch = search;
  194.   }
  195.   /**
  196.    * Get the name of the attribute/subset evaluator
  197.    *
  198.    * @return the name of the attribute/subset evaluator as a string
  199.    */
  200.   public ASEvaluation getEvaluator() {
  201.     
  202.       return m_ASEvaluator;
  203.   }
  204.   /**
  205.    * Get the name of the search method
  206.    *
  207.    * @return the name of the search method as a string
  208.    */
  209.   public ASSearch getSearch() {
  210.     
  211.       return m_ASSearch;
  212.   }
  213.   /**
  214.    * Input an instance for filtering. Ordinarily the instance is processed
  215.    * and made available for output immediately. Some filters require all
  216.    * instances be read before producing output.
  217.    *
  218.    * @param instance the input instance
  219.    * @return true if the filtered instance may now be
  220.    * collected with output().
  221.    * @exception IllegalStateException if no input format has been defined.
  222.    * @exception Exception if the input instance was not of the correct format 
  223.    * or if there was a problem with the filtering.
  224.    */
  225.   public boolean input(Instance instance) throws Exception {
  226.     
  227.     if (getInputFormat() == null) {
  228.       throw new IllegalStateException("No input instance format defined");
  229.     }
  230.     if (m_NewBatch) {
  231.       resetQueue();
  232.       m_NewBatch = false;
  233.     }
  234.     if (isOutputFormatDefined()) {
  235.       convertInstance(instance);
  236.       return true;
  237.     }
  238.     bufferInput(instance);
  239.     return false;
  240.   }
  241.   /**
  242.    * Signify that this batch of input to the filter is finished. If the filter
  243.    * requires all instances prior to filtering, output() may now be called
  244.    * to retrieve the filtered instances.
  245.    *
  246.    * @return true if there are instances pending output.
  247.    * @exception IllegalStateException if no input structure has been defined.
  248.    * @exception Exception if there is a problem during the attribute selection.
  249.    */
  250.   public boolean batchFinished() throws Exception {
  251.     
  252.     if (getInputFormat() == null) {
  253.       throw new IllegalStateException("No input instance format defined");
  254.     }
  255.     if (!isOutputFormatDefined()) {
  256.       m_trainSelector.setEvaluator(m_ASEvaluator);
  257.       m_trainSelector.setSearch(m_ASSearch);
  258.       m_trainSelector.SelectAttributes(getInputFormat());
  259.       //      System.out.println(m_trainSelector.toResultsString());
  260.       m_SelectedAttributes = m_trainSelector.selectedAttributes();
  261.       if (m_SelectedAttributes == null) {
  262. throw new Exception("No selected attributesn");
  263.       }
  264.      
  265.       setOutputFormat();
  266.       
  267.       // Convert pending input instances
  268.       for (int i = 0; i < getInputFormat().numInstances(); i++) {
  269. convertInstance(getInputFormat().instance(i));
  270.       }
  271.       flushInput();
  272.     }
  273.     
  274.     m_NewBatch = true;
  275.     return (numPendingOutput() != 0);
  276.   }
  277.   /**
  278.    * Set the output format. Takes the currently defined attribute set 
  279.    * m_InputFormat and calls setOutputFormat(Instances) appropriately.
  280.    */
  281.   protected void setOutputFormat() throws Exception {
  282.     Instances informat;
  283.     if (m_SelectedAttributes == null) {
  284.       setOutputFormat(null);
  285.       return;
  286.     }
  287.     FastVector attributes = new FastVector(m_SelectedAttributes.length);
  288.     int i;
  289.     if (m_ASEvaluator instanceof AttributeTransformer) {
  290.       informat = ((AttributeTransformer)m_ASEvaluator).transformedData();
  291.     } else {
  292.       informat = getInputFormat();
  293.     }
  294.     for (i=0;i < m_SelectedAttributes.length;i++) {
  295.       attributes.
  296. addElement(informat.attribute(m_SelectedAttributes[i]).copy());
  297.     }
  298.     Instances outputFormat = 
  299.       new Instances(getInputFormat().relationName(), attributes, 0);
  300.     if (!(m_ASEvaluator instanceof UnsupervisedSubsetEvaluator) &&
  301. !(m_ASEvaluator instanceof UnsupervisedAttributeEvaluator)) {
  302.       outputFormat.setClassIndex(m_SelectedAttributes.length - 1);
  303.     }
  304.     
  305.     setOutputFormat(outputFormat);  
  306.   }
  307.   /**
  308.    * Convert a single instance over. Selected attributes only are transfered.
  309.    * The converted instance is added to the end of
  310.    * the output queue.
  311.    *
  312.    * @param instance the instance to convert
  313.    */
  314.   protected void convertInstance(Instance instance) throws Exception {
  315.     int index = 0;
  316.     Instance newInstance;
  317.     double[] newVals = new double[getOutputFormat().numAttributes()];
  318.     if (m_ASEvaluator instanceof AttributeTransformer) {
  319.       Instance tempInstance = ((AttributeTransformer)m_ASEvaluator).
  320. convertInstance(instance);
  321.       for (int i = 0; i < m_SelectedAttributes.length; i++) {
  322. int current = m_SelectedAttributes[i];
  323. newVals[i] = tempInstance.value(current);
  324.       }
  325.     } else {
  326.       for (int i = 0; i < m_SelectedAttributes.length; i++) {
  327. int current = m_SelectedAttributes[i];
  328. newVals[i] = instance.value(current);
  329.       }
  330.     }
  331.     if (instance instanceof SparseInstance) {
  332.       push(new SparseInstance(instance.weight(), newVals));
  333.     } else {
  334.       push(new Instance(instance.weight(), newVals));
  335.     }
  336.   }
  337.   /**
  338.    * set options to their default values
  339.    */
  340.   protected void resetOptions() {
  341.     m_trainSelector = new AttributeSelection();
  342.     setEvaluator(new CfsSubsetEval());
  343.     setSearch(new BestFirst());
  344.     m_SelectedAttributes = null;
  345.     m_FilterOptions = null;
  346.   }
  347.   /**
  348.    * Main method for testing this class.
  349.    *
  350.    * @param argv should contain arguments to the filter: use -h for help
  351.    */
  352.   public static void main(String [] argv) {
  353.     
  354.     try {
  355.       if (Utils.getFlag('b', argv)) {
  356.   Filter.batchFilterFile(new AttributeSelectionFilter(), argv);
  357.       } else {
  358. Filter.filterFile(new AttributeSelectionFilter(), argv);
  359.       }
  360.     } catch (Exception ex) {
  361.       System.out.println(ex.getMessage());
  362.     }
  363.   }
  364. }