MOA 12.03
Real Time Analytics for Data Streams
|
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 }