~ubuntu-branches/ubuntu/precise/weka/precise

« back to all changes in this revision

Viewing changes to weka/estimators/MahalanobisEstimator.java

  • Committer: Bazaar Package Importer
  • Author(s): Soeren Sonnenburg
  • Date: 2008-02-24 09:18:45 UTC
  • Revision ID: james.westby@ubuntu.com-20080224091845-1l8zy6fm6xipbzsr
Tags: upstream-3.5.7+tut1
ImportĀ upstreamĀ versionĀ 3.5.7+tut1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 *    MahalanobisEstimator.java
 
19
 *    Copyright (C) 1999 University of Waikato, Hamilton, New Zealand
 
20
 *
 
21
 */
 
22
 
 
23
package weka.estimators;
 
24
 
 
25
import weka.core.Capabilities.Capability;
 
26
import weka.core.matrix.Matrix;
 
27
import weka.core.Capabilities;
 
28
import weka.core.Utils;
 
29
 
 
30
/** 
 
31
 * Simple probability estimator that places a single normal distribution
 
32
 * over the observed values.
 
33
 *
 
34
 * @author Len Trigg (trigg@cs.waikato.ac.nz)
 
35
 * @version $Revision: 1.7 $
 
36
 */
 
37
public class MahalanobisEstimator extends Estimator implements IncrementalEstimator {
 
38
  
 
39
  /** for serialization  */
 
40
  private static final long serialVersionUID = 8950225468990043868L;
 
41
  
 
42
  /** The inverse of the covariance matrix */
 
43
  private Matrix m_CovarianceInverse;
 
44
  
 
45
  /** The determinant of the covariance matrix */
 
46
  private double m_Determinant;
 
47
  
 
48
  /**
 
49
   * The difference between the conditioning value and the conditioning mean
 
50
   */
 
51
  private double m_ConstDelta;
 
52
  
 
53
  /** The mean of the values */
 
54
  private double m_ValueMean;
 
55
  
 
56
  /** 2 * PI */
 
57
  private static double TWO_PI = 2 * Math.PI;
 
58
  
 
59
  /**
 
60
   * Returns value for normal kernel
 
61
   *
 
62
   * @param x the argument to the kernel function
 
63
   * @param variance the variance
 
64
   * @return the value for a normal kernel
 
65
   */
 
66
  private double normalKernel(double x) {
 
67
    
 
68
    Matrix thisPoint = new Matrix(1, 2);
 
69
    thisPoint.set(0, 0, x);
 
70
    thisPoint.set(0, 1, m_ConstDelta);
 
71
    return Math.exp(-thisPoint.times(m_CovarianceInverse).
 
72
        times(thisPoint.transpose()).get(0, 0) 
 
73
        / 2) / (Math.sqrt(TWO_PI) * m_Determinant);
 
74
  }
 
75
  
 
76
  /**
 
77
   * Constructor
 
78
   *
 
79
   * @param covariance
 
80
   * @param constDelta
 
81
   * @param valueMean
 
82
   */
 
83
  public MahalanobisEstimator(Matrix covariance, double constDelta,
 
84
      double valueMean) {
 
85
    
 
86
    m_CovarianceInverse = null;
 
87
    if ((covariance.getRowDimension() == 2) && (covariance.getColumnDimension() == 2)) {
 
88
      double a = covariance.get(0, 0);
 
89
      double b = covariance.get(0, 1);
 
90
      double c = covariance.get(1, 0);
 
91
      double d = covariance.get(1, 1);
 
92
      if (a == 0) {
 
93
        a = c; c = 0;
 
94
        double temp = b;
 
95
        b = d; d = temp;
 
96
      }
 
97
      if (a == 0) {
 
98
        return;
 
99
      }
 
100
      double denom = d - c * b / a;
 
101
      if (denom == 0) {
 
102
        return;
 
103
      }
 
104
      m_Determinant = covariance.get(0, 0) * covariance.get(1, 1)
 
105
      - covariance.get(1, 0) * covariance.get(0, 1);
 
106
      m_CovarianceInverse = new Matrix(2, 2);
 
107
      m_CovarianceInverse.set(0, 0, 1.0 / a + b * c / a / a / denom);
 
108
      m_CovarianceInverse.set(0, 1, -b / a / denom);
 
109
      m_CovarianceInverse.set(1, 0, -c / a / denom);
 
110
      m_CovarianceInverse.set(1, 1, 1.0 / denom);
 
111
      m_ConstDelta = constDelta;
 
112
      m_ValueMean = valueMean;
 
113
    }
 
114
  }
 
115
  
 
116
  /**
 
117
   * Add a new data value to the current estimator. Does nothing because the
 
118
   * data is provided in the constructor.
 
119
   *
 
120
   * @param data the new data value 
 
121
   * @param weight the weight assigned to the data value 
 
122
   */
 
123
  public void addValue(double data, double weight) {
 
124
    
 
125
  }
 
126
  
 
127
  /**
 
128
   * Get a probability estimate for a value
 
129
   *
 
130
   * @param data the value to estimate the probability of
 
131
   * @return the estimated probability of the supplied value
 
132
   */
 
133
  public double getProbability(double data) {
 
134
    
 
135
    double delta = data - m_ValueMean;
 
136
    if (m_CovarianceInverse == null) {
 
137
      return 0;
 
138
    }
 
139
    return normalKernel(delta);
 
140
  }
 
141
  
 
142
  /** Display a representation of this estimator */
 
143
  public String toString() {
 
144
    
 
145
    if (m_CovarianceInverse == null) {
 
146
      return "No covariance inverse\n";
 
147
    }
 
148
    return "Mahalanovis Distribution. Mean = "
 
149
    + Utils.doubleToString(m_ValueMean, 4, 2)
 
150
    + "  ConditionalOffset = "
 
151
    + Utils.doubleToString(m_ConstDelta, 4, 2) + "\n"
 
152
    + "Covariance Matrix: Determinant = " + m_Determinant 
 
153
    + "  Inverse:\n" + m_CovarianceInverse;
 
154
  }
 
155
  
 
156
  /**
 
157
   * Returns default capabilities of the classifier.
 
158
   *
 
159
   * @return      the capabilities of this classifier
 
160
   */
 
161
  public Capabilities getCapabilities() {
 
162
    Capabilities result = super.getCapabilities();
 
163
    
 
164
    // attributes
 
165
    result.enable(Capability.NUMERIC_ATTRIBUTES);
 
166
    return result;
 
167
  }
 
168
  
 
169
  
 
170
  /**
 
171
   * Main method for testing this class.
 
172
   *
 
173
   * @param argv should contain a sequence of numeric values
 
174
   */
 
175
  public static void main(String [] argv) {
 
176
    
 
177
    try {
 
178
      double delta = 0.5;
 
179
      double xmean = 0;
 
180
      double lower = 0;
 
181
      double upper = 10;
 
182
      Matrix covariance = new Matrix(2, 2);
 
183
      covariance.set(0, 0, 2);
 
184
      covariance.set(0, 1, -3);
 
185
      covariance.set(1, 0, -4);
 
186
      covariance.set(1, 1, 5);
 
187
      if (argv.length > 0) {
 
188
        covariance.set(0, 0, Double.valueOf(argv[0]).doubleValue());
 
189
      }
 
190
      if (argv.length > 1) {
 
191
        covariance.set(0, 1, Double.valueOf(argv[1]).doubleValue());
 
192
      }
 
193
      if (argv.length > 2) {
 
194
        covariance.set(1, 0, Double.valueOf(argv[2]).doubleValue());
 
195
      }
 
196
      if (argv.length > 3) {
 
197
        covariance.set(1, 1, Double.valueOf(argv[3]).doubleValue());
 
198
      }
 
199
      if (argv.length > 4) {
 
200
        delta = Double.valueOf(argv[4]).doubleValue();
 
201
      }
 
202
      if (argv.length > 5) {
 
203
        xmean = Double.valueOf(argv[5]).doubleValue();
 
204
      }
 
205
      
 
206
      MahalanobisEstimator newEst = new MahalanobisEstimator(covariance,
 
207
          delta, xmean);
 
208
      if (argv.length > 6) {
 
209
        lower = Double.valueOf(argv[6]).doubleValue();
 
210
        if (argv.length > 7) {
 
211
          upper = Double.valueOf(argv[7]).doubleValue();
 
212
        }
 
213
        double increment = (upper - lower) / 50;
 
214
        for(double current = lower; current <= upper; current+= increment)
 
215
          System.out.println(current + "  " + newEst.getProbability(current));
 
216
      } else {
 
217
        System.out.println("Covariance Matrix\n" + covariance);
 
218
        System.out.println(newEst);
 
219
      }
 
220
    } catch (Exception e) {
 
221
      System.out.println(e.getMessage());
 
222
    }
 
223
  }
 
224
}
 
225
 
 
226
 
 
227
 
 
228
 
 
229
 
 
230
 
 
231
 
 
232