source: src/main/java/weka/estimators/UnivariateNormalEstimator.java @ 12

Last change on this file since 12 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 6.7 KB
Line 
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/*
18 *    UnivariateNormalEstimator.java
19 *    Copyright (C) 2009 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23package weka.estimators;
24
25import java.util.Random;
26
27import weka.core.Statistics;
28
29/**
30 * Simple weighted normal density estimator.
31 *
32 * @author Eibe Frank (eibe@cs.waikato.ac.nz)
33 * @version $Revision: 5680 $
34 */
35public class UnivariateNormalEstimator implements UnivariateDensityEstimator,
36                                                  UnivariateIntervalEstimator {
37
38  /** The weighted sum of values */
39  protected double m_WeightedSum = 0;
40
41  /** The weighted sum of squared values */
42  protected double m_WeightedSumSquared = 0;
43
44  /** The weight of the values collected so far */
45  protected double m_SumOfWeights = 0;
46
47  /** The mean value (only updated when needed) */
48  protected double m_Mean = 0;
49
50  /** The variance (only updated when needed) */
51  protected double m_Variance = Double.MAX_VALUE;
52
53  /** The minimum allowed value of the variance (default: 1.0E-6 * 1.0E-6) */
54  protected double m_MinVar = 1.0E-6 * 1.0E-6;
55
56  /** Constant for Gaussian density */
57  public static final double CONST = Math.log(2 * Math.PI);
58
59  /**
60   * Adds a value to the density estimator.
61   *
62   * @param value the value to add
63   * @param weight the weight of the value
64   */
65  public void addValue(double value, double weight) {
66
67    m_WeightedSum += value * weight;
68    m_WeightedSumSquared += value * value * weight;
69    m_SumOfWeights += weight;
70  }
71
72  /**
73   * Updates mean and variance based on sufficient statistics.
74   * Variance is set to m_MinVar if it becomes smaller than that
75   * value. It is set to Double.MAX_VALUE if the sum of weights is
76   * zero.
77   */
78  protected void updateMeanAndVariance() {
79   
80    // Compute mean
81    m_Mean = 0;
82    if (m_SumOfWeights > 0) {
83      m_Mean = m_WeightedSum / m_SumOfWeights;
84    }
85
86    // Compute variance
87    m_Variance = Double.MAX_VALUE;
88    if (m_SumOfWeights > 0) {
89      m_Variance = m_WeightedSumSquared / m_SumOfWeights - m_Mean * m_Mean; 
90    }
91
92    // Hack for case where variance is 0
93    if (m_Variance <= m_MinVar) {
94      m_Variance = m_MinVar;
95    }
96  }
97
98  /**
99   * Returns the interval for the given confidence value.
100   *
101   * @param conf the confidence value in the interval [0, 1]
102   * @return the interval
103   */
104  public double[][] predictIntervals(double conf) {
105   
106    updateMeanAndVariance();
107
108    double val = Statistics.normalInverse(1.0 - (1.0 - conf) / 2.0);
109
110    double[][] arr = new double[1][2];
111    arr[0][1] = m_Mean + val * Math.sqrt(m_Variance);
112    arr[0][0] = m_Mean - val * Math.sqrt(m_Variance);
113
114    return arr;
115  }
116
117  /**
118   * Returns the natural logarithm of the density estimate at the given
119   * point.
120   *
121   * @param value the value at which to evaluate
122   * @return the natural logarithm of the density estimate at the given
123   * value
124   */
125  public double logDensity(double value) {
126   
127    updateMeanAndVariance();
128
129    // Return natural logarithm of density
130    double val = -0.5 * (CONST + Math.log(m_Variance) + 
131                         (value - m_Mean) * (value - m_Mean) / m_Variance); 
132
133    return val;
134  }
135
136  /**
137   * Returns textual description of this estimator.
138   */
139  public String toString() {
140
141    updateMeanAndVariance();
142
143    return "Mean: " + m_Mean + "\t" + "Variance: " + m_Variance;
144  }
145
146  /**
147   * Main method, used for testing this class.
148   */
149  public static void main(String[] args) {
150
151    // Get random number generator initialized by system
152    Random r = new Random();
153
154    // Create density estimator
155    UnivariateNormalEstimator e = new UnivariateNormalEstimator();
156
157    // Output the density estimator
158    System.out.println(e);
159
160    // Monte Carlo integration
161    double sum = 0;
162    for (int i = 0; i < 100000; i++) {
163      sum += Math.exp(e.logDensity(r.nextDouble() * 10.0 - 5.0));
164    }
165    System.out.println("Approximate integral: " + 10.0 * sum / 100000);
166
167    // Add Gaussian values into it
168    for (int i = 0; i < 100000; i++) {
169      e.addValue(r.nextGaussian(), 1);
170      e.addValue(r.nextGaussian() * 2.0, 3);
171    }
172
173    // Output the density estimator
174    System.out.println(e);
175
176    // Monte Carlo integration
177    sum = 0;
178    for (int i = 0; i < 100000; i++) {
179      sum += Math.exp(e.logDensity(r.nextDouble() * 10.0 - 5.0));
180    }
181    System.out.println("Approximate integral: " + 10.0 * sum / 100000);
182
183    // Create density estimator
184    e = new UnivariateNormalEstimator();
185
186    // Add Gaussian values into it
187    for (int i = 0; i < 100000; i++) {
188      e.addValue(r.nextGaussian(), 1);
189      e.addValue(r.nextGaussian() * 2.0, 1);
190      e.addValue(r.nextGaussian() * 2.0, 1);
191      e.addValue(r.nextGaussian() * 2.0, 1);
192    }
193
194    // Output the density estimator
195    System.out.println(e);
196
197    // Monte Carlo integration
198    sum = 0;
199    for (int i = 0; i < 100000; i++) {
200      sum += Math.exp(e.logDensity(r.nextDouble() * 10.0 - 5.0));
201    }
202    System.out.println("Approximate integral: " + 10.0 * sum / 100000);
203
204    // Create density estimator
205    e = new UnivariateNormalEstimator();
206
207    // Add Gaussian values into it
208    for (int i = 0; i < 100000; i++) {
209      e.addValue(r.nextGaussian() * 5.0 + 3.0 , 1);
210    }
211
212    // Output the density estimator
213    System.out.println(e);
214
215    // Check interval estimates
216    double[][] intervals = e.predictIntervals(0.95);
217    System.out.println("Lower: " + intervals[0][0] + " Upper: " + intervals[0][1]);
218    double covered = 0;
219    for (int i = 0; i < 100000; i++) {
220      double val = r.nextGaussian() * 5.0 + 3.0;
221      if (val >= intervals[0][0] && val <= intervals[0][1]) {
222        covered++;
223      }
224    }
225    System.out.println("Coverage: " + covered / 100000);
226
227    intervals = e.predictIntervals(0.8);
228    System.out.println("Lower: " + intervals[0][0] + " Upper: " + intervals[0][1]);
229    covered = 0;
230    for (int i = 0; i < 100000; i++) {
231      double val = r.nextGaussian() * 5.0 + 3.0;
232      if (val >= intervals[0][0] && val <= intervals[0][1]) {
233        covered++;
234      }
235    }
236    System.out.println("Coverage: " + covered / 100000);
237  }
238}
Note: See TracBrowser for help on using the repository browser.