MOA 12.03
Real Time Analytics for Data Streams
|
00001 /* 00002 * BasicClassificationPerformanceEvaluator.java 00003 * Copyright (C) 2007 University of Waikato, Hamilton, New Zealand 00004 * @author Richard Kirkby (rkirkby@cs.waikato.ac.nz) 00005 * @author Albert Bifet (abifet at cs dot waikato dot ac dot nz) 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 3 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 * 00020 */ 00021 package moa.evaluation; 00022 00023 import moa.AbstractMOAObject; 00024 import moa.core.Measurement; 00025 import weka.core.Utils; 00026 import weka.core.Instance; 00027 00035 public class BasicClassificationPerformanceEvaluator extends AbstractMOAObject 00036 implements ClassificationPerformanceEvaluator { 00037 00038 private static final long serialVersionUID = 1L; 00039 00040 protected double weightObserved; 00041 00042 protected double weightCorrect; 00043 00044 protected double[] columnKappa; 00045 00046 protected double[] rowKappa; 00047 00048 protected int numClasses; 00049 00050 @Override 00051 public void reset() { 00052 reset(this.numClasses); 00053 } 00054 00055 public void reset(int numClasses) { 00056 this.numClasses = numClasses; 00057 this.rowKappa = new double[numClasses]; 00058 this.columnKappa = new double[numClasses]; 00059 for (int i = 0; i < this.numClasses; i++) { 00060 this.rowKappa[i] = 0.0; 00061 this.columnKappa[i] = 0.0; 00062 } 00063 this.weightObserved = 0.0; 00064 this.weightCorrect = 0.0; 00065 } 00066 00067 @Override 00068 public void addResult(Instance inst, double[] classVotes) { 00069 double weight = inst.weight(); 00070 int trueClass = (int) inst.classValue(); 00071 if (weight > 0.0) { 00072 if (this.weightObserved == 0) { 00073 reset(inst.dataset().numClasses()); 00074 } 00075 this.weightObserved += weight; 00076 int predictedClass = Utils.maxIndex(classVotes); 00077 if (predictedClass == trueClass) { 00078 this.weightCorrect += weight; 00079 } 00080 this.rowKappa[predictedClass] += weight; 00081 this.columnKappa[trueClass] += weight; 00082 } 00083 } 00084 00085 @Override 00086 public Measurement[] getPerformanceMeasurements() { 00087 return new Measurement[]{ 00088 new Measurement("classified instances", 00089 getTotalWeightObserved()), 00090 new Measurement("classifications correct (percent)", 00091 getFractionCorrectlyClassified() * 100.0), 00092 new Measurement("Kappa Statistic (percent)", 00093 getKappaStatistic() * 100.0)}; 00094 00095 } 00096 00097 public double getTotalWeightObserved() { 00098 return this.weightObserved; 00099 } 00100 00101 public double getFractionCorrectlyClassified() { 00102 return this.weightObserved > 0.0 ? this.weightCorrect 00103 / this.weightObserved : 0.0; 00104 } 00105 00106 public double getFractionIncorrectlyClassified() { 00107 return 1.0 - getFractionCorrectlyClassified(); 00108 } 00109 00110 public double getKappaStatistic() { 00111 if (this.weightObserved > 0.0) { 00112 double p0 = getFractionCorrectlyClassified(); 00113 double pc = 0.0; 00114 for (int i = 0; i < this.numClasses; i++) { 00115 pc += (this.rowKappa[i] / this.weightObserved) 00116 * (this.columnKappa[i] / this.weightObserved); 00117 } 00118 return (p0 - pc) / (1.0 - pc); 00119 } else { 00120 return 0; 00121 } 00122 } 00123 00124 @Override 00125 public void getDescription(StringBuilder sb, int indent) { 00126 Measurement.getMeasurementsDescription(getPerformanceMeasurements(), 00127 sb, indent); 00128 } 00129 }