Package weka.estimators

Source Code of weka.estimators.Estimator$Builder

/*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program; if not, write to the Free Software
*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
*    Estimator.java
*    Copyright (C) 1999 University of Waikato, Hamilton, New Zealand
*
*/

package weka.estimators;

import weka.core.Capabilities;
import weka.core.CapabilitiesHandler;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.Option;
import weka.core.OptionHandler;
import weka.core.RevisionHandler;
import weka.core.RevisionUtils;
import weka.core.SerializedObject;
import weka.core.Utils;
import weka.core.Capabilities.Capability;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;
/**
*
* Abstract class for all estimators.
*
* Example code for a nonincremental estimator
* <code> <pre>
*   // create a histogram for estimation
*   EqualWidthEstimator est = new EqualWidthEstimator();
*   est.addValues(instances, attrIndex);
* </pre> </code>
*
*
* Example code for an incremental estimator (incremental
* estimators must implement interface IncrementalEstimator)
* <code> <pre>
*   // Create a discrete estimator that takes values 0 to 9
*   DiscreteEstimator newEst = new DiscreteEstimator(10, true);
*
*   // Create 50 random integers first predicting the probability of the
*   // value, then adding the value to the estimator
*   Random r = new Random(seed);
*   for(int i = 0; i < 50; i++) {
*     current = Math.abs(r.nextInt() % 10);
*     System.out.println(newEst);
*     System.out.println("Prediction for " + current
*                        + " = " + newEst.getProbability(current));
*     newEst.addValue(current, 1);
*   }
* </pre> </code>
*
*
* Example code for a main method for an estimator.<p>
* <code> <pre>
* public static void main(String [] argv) {
*
*   try {
*     LoglikeliEstimator est = new LoglikeliEstimator();     
*     Estimator.buildEstimator((Estimator) est, argv, false);     
*     System.out.println(est.toString());
*   } catch (Exception ex) {
*     ex.printStackTrace();
*     System.out.println(ex.getMessage());
*   }
* }
* </pre> </code>
*
*
* @author Gabi Schmidberger (gabi@cs.waikato.ac.nz)
* @author Len Trigg (trigg@cs.waikato.ac.nz)
* @version $Revision: 5489 $
*/
public abstract class Estimator
  implements Cloneable, Serializable, OptionHandler, CapabilitiesHandler,
             RevisionHandler {
 
  /** for serialization */
  static final long serialVersionUID = -5902411487362274342L;
 
  /** Debugging mode */
  private boolean m_Debug = false;
 
  /** The class value index is > -1 if subset is taken with specific class value only*/
  protected double m_classValueIndex = -1.0;
 
  /** set if class is not important */
  protected boolean m_noClass = true;
 
  /**
   * Class to support a building process of an estimator.
   */
  private static class Builder
    implements Serializable, RevisionHandler {

    /** for serialization */
    private static final long serialVersionUID = -5810927990193597303L;
   
    /** instances of the builder */
    Instances m_instances = null;
   
    /** attribute index of the builder */
    int m_attrIndex = -1;
   
    /** class index of the builder, only relevant if class value index is set*/
    int m_classIndex = -1;

    /** class value index of the builder */
    int m_classValueIndex = -1;
   
    /**
     * Returns the revision string.
     *
     * @return    the revision
     */
    public String getRevision() {
      return RevisionUtils.extract("$Revision: 5489 $");
    }
  }
 
  /**
   * Add a new data value to the current estimator.
   *
   * @param data the new data value
   * @param weight the weight assigned to the data value
   */
  public void addValue(double data, double weight) {
    try
      throw new Exception("Method to add single value is not implemented!\n"+
        "Estimator should implement IncrementalEstimator.");
    } catch (Exception ex) {
      ex.printStackTrace();
      System.out.println(ex.getMessage());
    }
  }

  /**
   * Initialize the estimator with a new dataset.
   * Finds min and max first.
   *
   * @param data the dataset used to build this estimator
   * @param attrIndex attribute the estimator is for
   * @exception Exception if building of estimator goes wrong
   */
  public void addValues(Instances data, int attrIndex) throws Exception {
    // can estimator handle the data?
    getCapabilities().testWithFail(data);
  
    double []minMax = new double[2];
   
    try {
      EstimatorUtils.getMinMax(data, attrIndex, minMax);
    } catch (Exception ex) {
      ex.printStackTrace();
      System.out.println(ex.getMessage());
    }
   
    double min = minMax[0];
    double max = minMax[1];

    // factor is 1.0, data set has not been reduced
    addValues(data, attrIndex, min, max, 1.0);
  }
 
  /**
   * Initialize the estimator with all values of one attribute of a dataset.
   * Some estimator might ignore the min and max values.
   *
   * @param data the dataset used to build this estimator
   * @param attrIndex attribute the estimator is for
   * @param min minimal border of range
   * @param max maximal border of range
   * @param factor number of instances has been reduced to that factor
   * @exception Exception if building of estimator goes wrong
   */
  public void addValues(Instances data, int attrIndex,
      double min, double max, double factor) throws Exception {
    // no handling of factor, would have to be overridden

    // no handling of min and max, would have to be overridden

    int numInst = data.numInstances();
    for (int i = 1; i < numInst; i++) {
      addValue(data.instance(i).value(attrIndex), 1.0);
    }
  }
  /**
   * Initialize the estimator using only the instance of one class.
   * It is using the values of one attribute only.
   *
   * @param data the dataset used to build this estimator
   * @param attrIndex attribute the estimator is for
   * @param classIndex index of the class attribute
   * @param classValue the class value
   * @exception Exception if building of estimator goes wrong
   */
  public void addValues(Instances data, int attrIndex,
      int classIndex, int classValue) throws Exception{
    // can estimator handle the data?
    m_noClass = false;   
    getCapabilities().testWithFail(data);
   
    // find the minimal and the maximal value
    double []minMax = new double[2];
   
    try {
      EstimatorUtils.getMinMax(data, attrIndex, minMax);
    } catch (Exception ex) {
      ex.printStackTrace();
      System.out.println(ex.getMessage());
    }
   
    double min = minMax[0];
    double max = minMax[1];
    // extract the instances with the given class value
    Instances workData = new Instances(data, 0);
    double factor = getInstancesFromClass(data, attrIndex,
            classIndex,
            (double)classValue, workData);

    // if no data return
    if (workData.numInstances() == 0) return;

    addValues(data, attrIndex, min, max, factor);
  }
 
  /**
   * Initialize the estimator using only the instance of one class.
   * It is using the values of one attribute only.
   *
   * @param data the dataset used to build this estimator
   * @param attrIndex attribute the estimator is for
   * @param classIndex index of the class attribute
   * @param classValue the class value
   * @param min minimal value of this attribute
   * @param max maximal value of this attribute
   * @exception Exception if building of estimator goes wrong
   */
  public void addValues(Instances data, int attrIndex,
      int classIndex, int classValue,
      double min, double max) throws Exception{
    
    // extract the instances with the given class value
    Instances workData = new Instances(data, 0);
    double factor = getInstancesFromClass(data, attrIndex,
            classIndex,
            (double)classValue, workData);

    // if no data return
    if (workData.numInstances() == 0) return;

    addValues(data, attrIndex, min, max, factor);
  }
 
  /**
   * Returns a dataset that contains all instances of a certain class value.
   *
   * @param data dataset to select the instances from
   * @param attrIndex index of the relevant attribute
   * @param classIndex index of the class attribute
   * @param classValue the relevant class value
   * @return a dataset with only
   */
  private double getInstancesFromClass(Instances data, int attrIndex,
               int classIndex,
               double classValue, Instances workData) {
    //DBO.pln("getInstancesFromClass classValue"+classValue+" workData"+data.numInstances());

    int num = 0;
    int numClassValue = 0;
    for (int i = 0; i < data.numInstances(); i++) {
      if (!data.instance(i).isMissing(attrIndex)) {
  num++;
  if (data.instance(i).value(classIndex) == classValue) {
    workData.add(data.instance(i));
    numClassValue++;
  }
      }
    }

    Double alphaFactor = new Double((double)numClassValue/(double)num);
    return alphaFactor;
  }

  /**
   * Get a probability estimate for a value.
   *
   * @param data the value to estimate the probability of
   * @return the estimated probability of the supplied value
   */
  public abstract double getProbability(double data);

  /**
   * Build an estimator using the options. The data is given in the options.
   *
   * @param est the estimator used
   * @param options the list of options
   * @param isIncremental true if estimator is incremental
   * @exception Exception if something goes wrong or the user requests help on
   * command options
   */
  public static void buildEstimator(Estimator est, String [] options,
            boolean isIncremental)
    throws Exception {
    //DBO.pln("buildEstimator");
   
    boolean debug = false;
    boolean helpRequest;
   
    // read all options
    Builder build = new Builder();
    try {
      setGeneralOptions(build, est, options);
     
      if (est instanceof OptionHandler) {
  ((OptionHandler)est).setOptions(options);
      }
     
      Utils.checkForRemainingOptions(options);
     
   
      buildEstimator(est, build.m_instances, build.m_attrIndex,
         build.m_classIndex, build.m_classValueIndex, isIncremental);
    } catch (Exception ex) {
      ex.printStackTrace();
      System.out.println(ex.getMessage());
      String specificOptions = "";
      // Output the error and also the valid options
      if (est instanceof OptionHandler) {
  specificOptions += "\nEstimator options:\n\n";
  Enumeration enumOptions = ((OptionHandler)est).listOptions();
  while (enumOptions.hasMoreElements()) {
    Option option = (Option) enumOptions.nextElement();
    specificOptions += option.synopsis() + '\n'
      + option.description() + "\n";
  }
      }
     
      String genericOptions = "\nGeneral options:\n\n"
  + "-h\n"
  + "\tGet help on available options.\n"
  + "-i <file>\n"
  + "\tThe name of the file containing input instances.\n"
  + "\tIf not supplied then instances will be read from stdin.\n"
  + "-a <attribute index>\n"
  + "\tThe number of the attribute the probability distribution\n"
  + "\testimation is done for.\n"
  + "\t\"first\" and \"last\" are also valid entries.\n"
  + "\tIf not supplied then no class is assigned.\n"
  + "-c <class index>\n"
  + "\tIf class value index is set, this attribute is taken as class.\n"
  + "\t\"first\" and \"last\" are also valid entries.\n"
  + "\tIf not supplied then last is default.\n"
  + "-v <class value index>\n"
  + "\tIf value is different to -1, select instances of this class value.\n"
  + "\t\"first\" and \"last\" are also valid entries.\n"
  + "\tIf not supplied then all instances are taken.\n";
     
      throw new Exception('\n' + ex.getMessage()
        + specificOptions+genericOptions);
    }
  }

  public static void buildEstimator(Estimator est,
            Instances instances, int attrIndex,
            int classIndex, int classValueIndex,
            boolean isIncremental) throws Exception {

    // DBO.pln("buildEstimator 2 " + classValueIndex);

    // non-incremental estimator add all instances at once
    if (!isIncremental) {
     
      if (classValueIndex == -1) {
  // DBO.pln("before addValues -- Estimator");
  est.addValues(instances, attrIndex);
      } else {
  // DBO.pln("before addValues with classvalue -- Estimator");
  est.addValues(instances, attrIndex,
          classIndex, classValueIndex);
      }
    } else {
      // incremental estimator, read one value at a time
      Enumeration enumInsts = (instances).enumerateInstances();
      while (enumInsts.hasMoreElements()) {
  Instance instance =
    (Instance) enumInsts.nextElement();
  ((IncrementalEstimator)est).addValue(instance.value(attrIndex),
               instance.weight());
      }
    }
  }
 
  /**
   * Parses and sets the general options
   * @param build contains the data used
   * @param est the estimator used
   * @param options the options from the command line
   */
  private static void setGeneralOptions(Builder build, Estimator est,
          String [] options
    throws Exception {
    Reader input = null;
   
    // help request option
    boolean helpRequest = Utils.getFlag('h', options);
    if (helpRequest) {
      throw new Exception("Help requested.\n");
    }
   
    // instances used
    String infileName = Utils.getOption('i', options);
    if (infileName.length() != 0) {
      input = new BufferedReader(new FileReader(infileName));
    } else {
      input = new BufferedReader(new InputStreamReader(System.in));
    }
   
    build.m_instances = new Instances(input);
   
    // attribute index
    String attrIndex = Utils.getOption('a', options);
   
    if (attrIndex.length() != 0) {
      if (attrIndex.equals("first")) {
  build.m_attrIndex = 0;
      } else if (attrIndex.equals("last")) {
  build.m_attrIndex = build.m_instances.numAttributes() - 1;
      } else {
  int index = Integer.parseInt(attrIndex) - 1;
  if ((index < 0) || (index >= build.m_instances.numAttributes())) {
    throw new IllegalArgumentException("Option a: attribute index out of range.");
  }
  build.m_attrIndex = index;
 
      }
    } else {
      // default is the first attribute
      build.m_attrIndex = 0;
    }
   
    //class index, if not given is set to last attribute
    String classIndex = Utils.getOption('c', options);
    if (classIndex.length() == 0) classIndex = "last";

    if (classIndex.length() != 0) {
      if (classIndex.equals("first")) {
  build.m_classIndex = 0;
      } else if (classIndex.equals("last")) {
  build.m_classIndex = build.m_instances.numAttributes() - 1;
      } else {
  int cl = Integer.parseInt(classIndex);
  if (cl == -1) {
    build.m_classIndex = build.m_instances.numAttributes() - 1;
  } else {
    build.m_classIndex = cl - 1
  }
      }
    }
   
    //class value index, if not given is set to  -1
    String classValueIndex = Utils.getOption('v', options);
    if (classValueIndex.length() != 0) {
      if (classValueIndex.equals("first")) {
  build.m_classValueIndex = 0;
      } else if (classValueIndex.equals("last")) {
  build.m_classValueIndex = build.m_instances.numAttributes() - 1;
      } else {
  int cl = Integer.parseInt(classValueIndex);
  if (cl == -1) {
    build.m_classValueIndex = -1;
  } else {
    build.m_classValueIndex = cl - 1
  }
      }
    }
   
    build.m_instances.setClassIndex(build.m_classIndex);
  }
 
  /**
   * Creates a deep copy of the given estimator using serialization.
   *
   * @param model the estimator to copy
   * @return a deep copy of the estimator
   * @exception Exception if an error occurs
   */
  public static Estimator clone(Estimator model) throws Exception {
   
    return makeCopy(model);
  }
 
  /**
   * Creates a deep copy of the given estimator using serialization.
   *
   * @param model the estimator to copy
   * @return a deep copy of the estimator
   * @exception Exception if an error occurs
   */
  public static Estimator makeCopy(Estimator model) throws Exception {

    return (Estimator)new SerializedObject(model).getObject();
  }

  /**
   * Creates a given number of deep copies of the given estimator using serialization.
   *
   * @param model the estimator to copy
   * @param num the number of estimator copies to create.
   * @return an array of estimators.
   * @exception Exception if an error occurs
   */
  public static Estimator [] makeCopies(Estimator model,
           int num) throws Exception {

    if (model == null) {
      throw new Exception("No model estimator set");
    }
    Estimator [] estimators = new Estimator [num];
    SerializedObject so = new SerializedObject(model);
    for(int i = 0; i < estimators.length; i++) {
      estimators[i] = (Estimator) so.getObject();
    }
    return estimators;
  }
  /**
   * Tests whether the current estimation object is equal to another
   * estimation object
   *
   * @param obj the object to compare against
   * @return true if the two objects are equal
   */
  public boolean equals(Object obj) {
   
    if ((obj == null) || !(obj.getClass().equals(this.getClass()))) {
      return false;
    }
    Estimator cmp = (Estimator) obj;
    if (m_Debug != cmp.m_Debug) return false;
    if (m_classValueIndex != cmp.m_classValueIndex) return false;
    if (m_noClass != cmp.m_noClass) return false;
   
    return true;
  }

  /**
   * Returns an enumeration describing the available options.
   *
   * @return an enumeration of all the available options.
   */
  public Enumeration listOptions() {

    Vector newVector = new Vector(1);

    newVector.addElement(new Option(
        "\tIf set, estimator is run in debug mode and\n"
        + "\tmay output additional info to the console",
        "D", 0, "-D"));
    return newVector.elements();
  }

  /**
   * Parses a given list of options. Valid options are:<p>
   *
   * -D  <br>
   * If set, estimator is run in debug mode and
   * may output additional info to the console.<p>
   *
   * @param options the list of options as an array of strings
   * @exception Exception if an option is not supported
   */
  public void setOptions(String[] options) throws Exception {

    setDebug(Utils.getFlag('D', options));
  }

  /**
   * Gets the current settings of the Estimator.
   *
   * @return an array of strings suitable for passing to setOptions
   */
  public String [] getOptions() {

    String [] options;
    if (getDebug()) {
      options = new String[1];
      options[0] = "-D";
    } else {
      options = new String[0];
    }
    return options;
  }
 
  /**
   * Creates a new instance of a estimatorr given it's class name and
   * (optional) arguments to pass to it's setOptions method. If the
   * classifier implements OptionHandler and the options parameter is
   * non-null, the classifier will have it's options set.
   *
   * @param name the fully qualified class name of the estimatorr
   * @param options an array of options suitable for passing to setOptions. May
   * be null.
   * @return the newly created classifier, ready for use.
   * @exception Exception if the classifier name is invalid, or the options
   * supplied are not acceptable to the classifier
   */
  public static Estimator forName(String name,
      String [] options) throws Exception {
   
    return (Estimator)Utils.forName(Estimator.class,
        name,
        options);
  }

/**
   * Set debugging mode.
   *
   * @param debug true if debug output should be printed
   */
  public void setDebug(boolean debug) {

    m_Debug = debug;
  }

  /**
   * Get whether debugging is turned on.
   *
   * @return true if debugging output is on
   */
  public boolean getDebug() {

    return m_Debug;
  }
 
  /**
   * Returns the tip text for this property
   * @return tip text for this property suitable for
   * displaying in the explorer/experimenter gui
   */
  public String debugTipText() {
    return "If set to true, estimator may output additional info to " +
      "the console.";
  }
  /**
   * Returns the Capabilities of this Estimator. Derived estimators have to
   * override this method to enable capabilities.
   *
   * @return            the capabilities of this object
   * @see               Capabilities
   */
  public Capabilities getCapabilities() {
    Capabilities result = new Capabilities(this);
    result.enableAll();
   
/*    // class
    if (!m_noClass) {
      result.enable(Capability.NOMINAL_CLASS);
      result.enable(Capability.MISSING_CLASS_VALUES);
    } else {
      result.enable(Capability.NO_CLASS);
    } */
      
    return result;
  }
 
  /**
   * Returns the revision string.
   *
   * @return            the revision
   */
  public String getRevision() {
    return RevisionUtils.extract("$Revision: 5489 $");
  }
 
  /**
   * Test if the estimator can handle the data.
   * @param data the dataset the estimator takes an attribute from
   * @param attrIndex the index of the attribute
   * @see Capabilities
   */
  public void testCapabilities(Instances data, int attrIndex) throws Exception {
    getCapabilities().testWithFail(data);
    getCapabilities().testWithFail(data.attribute(attrIndex));
  }
}







TOP

Related Classes of weka.estimators.Estimator$Builder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.