NormalEstimator.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 5k
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.  *    NormalEstimator.java
  18.  *    Copyright (C) 1999 Len Trigg
  19.  *
  20.  */
  21. package weka.estimators;
  22. import java.util.*;
  23. import weka.core.*;
  24. /** 
  25.  * Simple probability estimator that places a single normal distribution
  26.  * over the observed values.
  27.  *
  28.  * @author Len Trigg (trigg@cs.waikato.ac.nz)
  29.  * @version $Revision: 1.5 $
  30.  */
  31. public class NormalEstimator implements Estimator {
  32.   /** The sum of the weights */
  33.   private double m_SumOfWeights;
  34.   /** The sum of the values seen */
  35.   private double m_SumOfValues;
  36.   /** The sum of the values squared */
  37.   private double m_SumOfValuesSq;
  38.   /** The current mean */
  39.   private double m_Mean;
  40.   /** The current standard deviation */
  41.   private double m_StandardDev;
  42.   /** The precision of numeric values ( = minimum std dev permitted) */
  43.   private double m_Precision;
  44.   /**
  45.    * Round a data value using the defined precision for this estimator
  46.    *
  47.    * @param data the value to round
  48.    * @return the rounded data value
  49.    */
  50.   private double round(double data) {
  51.     return Math.rint(data / m_Precision) * m_Precision;
  52.   }
  53.   
  54.   // ===============
  55.   // Public methods.
  56.   // ===============
  57.   
  58.   /**
  59.    * Constructor that takes a precision argument.
  60.    *
  61.    * @param precision the precision to which numeric values are given. For
  62.    * example, if the precision is stated to be 0.1, the values in the
  63.    * interval (0.25,0.35] are all treated as 0.3. 
  64.    */
  65.   public NormalEstimator(double precision) {
  66.     m_Precision = precision;
  67.     // Allow at most 3 sd's within one interval
  68.     m_StandardDev = m_Precision / (2 * 3);
  69.   }
  70.   /**
  71.    * Add a new data value to the current estimator.
  72.    *
  73.    * @param data the new data value 
  74.    * @param weight the weight assigned to the data value 
  75.    */
  76.   public void addValue(double data, double weight) {
  77.     if (weight == 0) {
  78.       return;
  79.     }
  80.     data = round(data);
  81.     m_SumOfWeights += weight;
  82.     m_SumOfValues += data * weight;
  83.     m_SumOfValuesSq += data * data * weight;
  84.     if (m_SumOfWeights > 0) {
  85.       m_Mean = m_SumOfValues / m_SumOfWeights;
  86.       double stdDev = Math.sqrt(Math.abs(m_SumOfValuesSq 
  87.   - m_Mean * m_SumOfValues) 
  88.  / m_SumOfWeights);
  89.       // If the stdDev ~= 0, we really have no idea of scale yet, 
  90.       // so stick with the default. Otherwise...
  91.       if (stdDev > 1e-10) {
  92. m_StandardDev = Math.max(m_Precision / (2 * 3), 
  93.  // allow at most 3sd's within one interval 
  94.  stdDev);
  95.       }
  96.     }
  97.   }
  98.   /**
  99.    * Get a probability estimate for a value
  100.    *
  101.    * @param data the value to estimate the probability of
  102.    * @return the estimated probability of the supplied value
  103.    */
  104.   public double getProbability(double data) {
  105.     data = round(data);
  106.     double zLower = (data - m_Mean - (m_Precision / 2)) / m_StandardDev;
  107.     double zUpper = (data - m_Mean + (m_Precision / 2)) / m_StandardDev;
  108.     
  109.     double pLower = Statistics.normalProbability(zLower);
  110.     double pUpper = Statistics.normalProbability(zUpper);
  111.     return pUpper - pLower;
  112.   }
  113.   /**
  114.    * Display a representation of this estimator
  115.    */
  116.   public String toString() {
  117.     return "Normal Distribution. Mean = " + Utils.doubleToString(m_Mean, 4)
  118.       + " StandardDev = " + Utils.doubleToString(m_StandardDev, 4)
  119.       + " WeightSum = " + Utils.doubleToString(m_SumOfWeights, 4)
  120.       + " Precision = " + m_Precision + "n";
  121.   }
  122.   /**
  123.    * Main method for testing this class.
  124.    *
  125.    * @param argv should contain a sequence of numeric values
  126.    */
  127.   public static void main(String [] argv) {
  128.     try {
  129.       if (argv.length == 0) {
  130. System.out.println("Please specify a set of instances.");
  131. return;
  132.       }
  133.       NormalEstimator newEst = new NormalEstimator(0.01);
  134.       for(int i = 0; i < argv.length; i++) {
  135. double current = Double.valueOf(argv[i]).doubleValue();
  136. System.out.println(newEst);
  137. System.out.println("Prediction for " + current 
  138.    + " = " + newEst.getProbability(current));
  139. newEst.addValue(current, 1);
  140.       }
  141.     } catch (Exception e) {
  142.       System.out.println(e.getMessage());
  143.     }
  144.   }
  145. }