| package com.yahoo.labs.samoa.moa.core; |
| |
| /* |
| * #%L |
| * SAMOA |
| * %% |
| * Copyright (C) 2007 University of Waikato, Hamilton, New Zealand |
| * %% |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * #L% |
| */ |
| |
| import com.yahoo.labs.samoa.moa.AbstractMOAObject; |
| |
| /** |
| * Gaussian incremental estimator that uses incremental method that is more resistant to floating point imprecision. for |
| * more info see Donald Knuth's "The Art of Computer Programming, Volume 2: Seminumerical Algorithms", section 4.2.2. |
| * |
| * @author Richard Kirkby (rkirkby@cs.waikato.ac.nz) |
| * @version $Revision: 7 $ |
| */ |
| public class GaussianEstimator extends AbstractMOAObject { |
| |
| private static final long serialVersionUID = 1L; |
| |
| protected double weightSum; |
| |
| protected double mean; |
| |
| protected double varianceSum; |
| |
| public static final double NORMAL_CONSTANT = Math.sqrt(2 * Math.PI); |
| |
| public void addObservation(double value, double weight) { |
| if (Double.isInfinite(value) || Double.isNaN(value)) { |
| return; |
| } |
| if (this.weightSum > 0.0) { |
| this.weightSum += weight; |
| double lastMean = this.mean; |
| this.mean += weight * (value - lastMean) / this.weightSum; |
| this.varianceSum += weight * (value - lastMean) * (value - this.mean); |
| } else { |
| this.mean = value; |
| this.weightSum = weight; |
| } |
| } |
| |
| public void addObservations(GaussianEstimator obs) { |
| // Follows Variance Combination Rule in Section 2 of |
| // Brian Babcock, Mayur Datar, Rajeev Motwani, Liadan O'Callaghan: |
| // Maintaining variance and k-medians over data stream windows. PODS 2003: |
| // 234-243 |
| // |
| if ((this.weightSum >= 0.0) && (obs.weightSum > 0.0)) { |
| double oldMean = this.mean; |
| this.mean = (this.mean * (this.weightSum / (this.weightSum + obs.weightSum))) |
| + (obs.mean * (obs.weightSum / (this.weightSum + obs.weightSum))); |
| this.varianceSum += obs.varianceSum + (this.weightSum * obs.weightSum / (this.weightSum + obs.weightSum) * |
| Math.pow(obs.mean - oldMean, 2)); |
| this.weightSum += obs.weightSum; |
| } |
| } |
| |
| public double getTotalWeightObserved() { |
| return this.weightSum; |
| } |
| |
| public double getMean() { |
| return this.mean; |
| } |
| |
| public double getStdDev() { |
| return Math.sqrt(getVariance()); |
| } |
| |
| public double getVariance() { |
| return this.weightSum > 1.0 ? this.varianceSum / (this.weightSum - 1.0) |
| : 0.0; |
| } |
| |
| public double probabilityDensity(double value) { |
| if (this.weightSum > 0.0) { |
| double stdDev = getStdDev(); |
| if (stdDev > 0.0) { |
| double diff = value - getMean(); |
| return (1.0 / (NORMAL_CONSTANT * stdDev)) |
| * Math.exp(-(diff * diff / (2.0 * stdDev * stdDev))); |
| } |
| return value == getMean() ? 1.0 : 0.0; |
| } |
| return 0.0; |
| } |
| |
| public double[] estimatedWeight_LessThan_EqualTo_GreaterThan_Value( |
| double value) { |
| double equalToWeight = probabilityDensity(value) * this.weightSum; |
| double stdDev = getStdDev(); |
| double lessThanWeight = stdDev > 0.0 ? com.yahoo.labs.samoa.moa.core.Statistics |
| .normalProbability((value - getMean()) / stdDev) |
| * this.weightSum - equalToWeight |
| : (value < getMean() ? this.weightSum - equalToWeight : 0.0); |
| double greaterThanWeight = this.weightSum - equalToWeight |
| - lessThanWeight; |
| if (greaterThanWeight < 0.0) { |
| greaterThanWeight = 0.0; |
| } |
| return new double[] { lessThanWeight, equalToWeight, greaterThanWeight }; |
| } |
| |
| @Override |
| public void getDescription(StringBuilder sb, int indent) { |
| // TODO Auto-generated method stub |
| } |
| } |