MOA 12.03
Real Time Analytics for Data Streams
WindowClassificationPerformanceEvaluator.java
Go to the documentation of this file.
00001 /*
00002  *    WindowClassificationPerformanceEvaluator.java
00003  *    Copyright (C) 2009 University of Waikato, Hamilton, New Zealand
00004  *    @author Albert Bifet (abifet@cs.waikato.ac.nz)
00005  *
00006  *    This program is free software; you can redistribute it and/or modify
00007  *    it under the terms of the GNU General Public License as published by
00008  *    the Free Software Foundation; either version 3 of the License, or
00009  *    (at your option) any later version.
00010  *
00011  *    This program is distributed in the hope that it will be useful,
00012  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *    GNU General Public License for more details.
00015  *
00016  *    You should have received a copy of the GNU General Public License
00017  *    along with this program. If not, see <http://www.gnu.org/licenses/>.
00018  *    
00019  */
00020 package moa.evaluation;
00021 
00022 import moa.core.Measurement;
00023 import moa.core.ObjectRepository;
00024 import moa.options.AbstractOptionHandler;
00025 import moa.options.IntOption;
00026 import moa.tasks.TaskMonitor;
00027 import weka.core.Utils;
00028 import weka.core.Instance;
00029 
00036 public class WindowClassificationPerformanceEvaluator extends AbstractOptionHandler
00037         implements ClassificationPerformanceEvaluator {
00038 
00039     private static final long serialVersionUID = 1L;
00040 
00041     public IntOption widthOption = new IntOption("width",
00042             'w', "Size of Window", 1000);
00043 
00044     protected double TotalweightObserved = 0;
00045 
00046     protected Estimator weightObserved;
00047 
00048     protected Estimator weightCorrect;
00049 
00050     protected Estimator[] columnKappa;
00051 
00052     protected Estimator[] rowKappa;
00053 
00054     protected int numClasses;
00055 
00056     public class Estimator {
00057 
00058         protected double[] window;
00059 
00060         protected int posWindow;
00061 
00062         protected int lenWindow;
00063 
00064         protected int SizeWindow;
00065 
00066         protected double sum;
00067 
00068         public Estimator(int sizeWindow) {
00069             window = new double[sizeWindow];
00070             SizeWindow = sizeWindow;
00071             posWindow = 0;
00072         }
00073 
00074         public void add(double value) {
00075             sum -= window[posWindow];
00076             sum += value;
00077             window[posWindow] = value;
00078             posWindow++;
00079             if (posWindow == SizeWindow) {
00080                 posWindow = 0;
00081             }
00082         }
00083 
00084         public double total() {
00085             return sum;
00086         }
00087     }
00088 
00089     /*   public void setWindowWidth(int w) {
00090     this.width = w;
00091     reset();
00092     }*/
00093     @Override
00094     public void reset() {
00095         reset(this.numClasses);
00096     }
00097 
00098     public void reset(int numClasses) {
00099         this.numClasses = numClasses;
00100         this.rowKappa = new Estimator[numClasses];
00101         this.columnKappa = new Estimator[numClasses];
00102         for (int i = 0; i < this.numClasses; i++) {
00103             this.rowKappa[i] = new Estimator(this.widthOption.getValue());
00104             this.columnKappa[i] = new Estimator(this.widthOption.getValue());
00105         }
00106         this.weightCorrect = new Estimator(this.widthOption.getValue());
00107         this.weightObserved = new Estimator(this.widthOption.getValue());
00108         this.TotalweightObserved = 0;
00109     }
00110 
00111     @Override
00112     public void addResult(Instance inst, double[] classVotes) {
00113         double weight = inst.weight();
00114         int trueClass = (int) inst.classValue();
00115         if (weight > 0.0) {
00116             if (TotalweightObserved == 0) {
00117                 reset(inst.dataset().numClasses());
00118             }
00119             this.TotalweightObserved += weight;
00120             this.weightObserved.add(weight);
00121             int predictedClass = Utils.maxIndex(classVotes);
00122             if (predictedClass == trueClass) {
00123                 this.weightCorrect.add(weight);
00124             } else {
00125                 this.weightCorrect.add(0);
00126             }
00127             //Add Kappa statistic information
00128             for (int i = 0; i < this.numClasses; i++) {
00129                 this.rowKappa[i].add(i == predictedClass ? weight : 0);
00130                 this.columnKappa[i].add(i == trueClass ? weight : 0);
00131             }
00132 
00133         }
00134     }
00135 
00136     /*  public void addClassificationAttempt(int trueClass, double[] classVotes,
00137     double weight) {
00138     if (weight > 0.0) {
00139     if (TotalweightObserved == 0) {
00140     reset(classVotes.length>1?classVotes.length:2);
00141     }
00142     this.TotalweightObserved += weight;
00143     this.weightObserved.add(weight);
00144     int predictedClass = Utils.maxIndex(classVotes);
00145     if (predictedClass == trueClass) {
00146     this.weightCorrect.add(weight);
00147     } else {
00148     this.weightCorrect.add(0);
00149     }
00150     //Add Kappa statistic information
00151     for (int i = 0; i < this.numClasses; i++) {
00152     this.rowKappa[i].add( i == predictedClass ? weight : 0);
00153     this.columnKappa[i].add( i == trueClass ? weight : 0);
00154     }
00155 
00156     }
00157     }*/
00158     @Override
00159     public Measurement[] getPerformanceMeasurements() {
00160         return new Measurement[]{
00161                     new Measurement("classified instances",
00162                     this.TotalweightObserved),
00163                     new Measurement("classifications correct (percent)",
00164                     getFractionCorrectlyClassified() * 100.0),
00165                     new Measurement("Kappa Statistic (percent)",
00166                     getKappaStatistic() * 100.0)};
00167 
00168     }
00169 
00170     public double getTotalWeightObserved() {
00171         return this.weightObserved.total();
00172     }
00173 
00174     public double getFractionCorrectlyClassified() {
00175         return this.weightObserved.total() > 0.0 ? (double) this.weightCorrect.total()
00176                 / this.weightObserved.total() : 0.0;
00177     }
00178 
00179     public double getKappaStatistic() {
00180         if (this.weightObserved.total() > 0.0) {
00181             double p0 = this.weightCorrect.total() / this.weightObserved.total();
00182             double pc = 0;
00183             for (int i = 0; i < this.numClasses; i++) {
00184                 pc += (this.rowKappa[i].total() / this.weightObserved.total())
00185                         * (this.columnKappa[i].total() / this.weightObserved.total());
00186             }
00187             return (p0 - pc) / (1 - pc);
00188         } else {
00189             return 0;
00190         }
00191     }
00192 
00193     public double getFractionIncorrectlyClassified() {
00194         return 1.0 - getFractionCorrectlyClassified();
00195     }
00196 
00197     @Override
00198     public void getDescription(StringBuilder sb, int indent) {
00199         Measurement.getMeasurementsDescription(getPerformanceMeasurements(),
00200                 sb, indent);
00201     }
00202 
00203     @Override
00204     public void prepareForUseImpl(TaskMonitor monitor,
00205             ObjectRepository repository) {
00206     }
00207 }
 All Classes Namespaces Files Functions Variables Enumerations