/*
* RapidMiner
*
* Copyright (C) 2001-2008 by Rapid-I and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapid-i.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.operator.performance;
import com.rapidminer.example.Attribute;
import com.rapidminer.example.Example;
import com.rapidminer.example.ExampleSet;
import com.rapidminer.operator.Operator;
import com.rapidminer.operator.OperatorException;
import com.rapidminer.tools.math.Averagable;
/**
* <p>Measures the number of times a regression prediction correctly determines the trend.
* This performance measure assumes that the attributes of each example represents the
* values of a time window, the label is a value after a certain horizon which should
* be predicted. All examples build a consecutive series description, i.e. the labels
* of all examples build the series itself (this is, for example, the case for a windowing
* step size of 1). This format will be delivered by the Series2ExampleSet operators provided by
* RapidMiner.</p>
*
* <p>Example: Lets think of a series v1...v10 and a sliding window with window width 3,
* step size 1 and prediction horizon 1. The resulting example set is then</p>
*
* <pre>
* T1 T2 T3 L P
* ---------------
* v1 v2 v3 v4 p1
* v2 v3 v4 v5 p2
* v3 v4 v5 v6 p3
* v4 v5 v6 v7 p4
* v5 v6 v7 v8 p5
* v6 v7 v8 v9 p6
* v7 v8 v9 v10 p7
* </pre>
*
* <p>The second last column (L) corresponds to the label, i.e. the value which should be
* predicted and the last column (P) corresponds to the predictions. The columns T1, T2,
* and T3 correspond to the regular attributes, i.e. the points which should be used as
* learning input.</p>
*
* <p>This performance measure then calculates the actuals trend between the last time point
* in the series (T3 here) and the actual label (L) and compares it to the trend between T3
* and the prediction (P), sums the products between both trends, and divides this sum by the
* total number of examples, i.e. [(if ((v4-v3)*(p1-v3)>=0), 1, 0) + (if ((v5-v4)*(p2-v4)>=0), 1, 0) +...] / 7 in this example.</p>
*
* @author Ingo Mierswa
* @version $Id: PredictionTrendAccuracy.java,v 1.7 2008/09/23 14:07:33 ingomierswa Exp $
*/
public class PredictionTrendAccuracy extends MeasuredPerformance implements ForecastingCriterion {
private static final long serialVersionUID = 4275593122138248581L;
private double length = 1.0d;
private double correctCounter = 0.0d;
private Operator parent;
public PredictionTrendAccuracy() {}
public PredictionTrendAccuracy(PredictionTrendAccuracy pta) {
super(pta);
this.length = pta.length;
this.correctCounter = pta.correctCounter;
this.parent = pta.parent;
}
public void setParent(Operator parent) {
this.parent = parent;
}
public String getName() {
return "prediction_trend_accuracy";
}
public String getDescription() {
return "Measures the average of times a regression prediction was able to correctly predict the trend of the regression.";
}
public void startCounting(ExampleSet eSet, boolean useExampleWeights) throws OperatorException {
super.startCounting(eSet, useExampleWeights);
Attribute labelAttribute = eSet.getAttributes().getLabel();
Attribute predictedLabelAttribute = eSet.getAttributes().getPredictedLabel();
Attribute weightAttribute = null;
if (useExampleWeights)
weightAttribute = eSet.getAttributes().getWeight();
double[] weights = new double[eSet.size()];
double[] labels = new double[eSet.size()];
double[] predictions = new double[eSet.size()];
int index = 0;
for (Example example : eSet) {
double weight = 1.0d;
if (weightAttribute != null)
weight = example.getValue(weightAttribute);
weights[index] = weight;
labels[index] = example.getValue(labelAttribute);
predictions[index]= example.getValue(predictedLabelAttribute);
index++;
}
int horizon = this.parent.getParameterAsInt(ForecastingPerformanceEvaluator.PARAMETER_HORIZON);
for (int i = horizon; i < labels.length; i++) {
double actualTrend = labels[i] - labels[i - horizon];
double predictionTrend = predictions[i] - predictions[i - horizon];
if (actualTrend * predictionTrend >= 0) {
correctCounter += weights[i - horizon];
}
length += weights[i - horizon];
}
}
public double getExampleCount() {
return length;
}
public void countExample(Example example) {}
public double getFitness() {
return getAverage();
}
public double getMikroAverage() {
return correctCounter / length;
}
public double getMikroVariance() {
return Double.NaN;
}
public void buildSingleAverage(Averagable averagable) {
PredictionTrendAccuracy other = (PredictionTrendAccuracy) averagable;
this.length += other.length;
this.correctCounter += other.correctCounter;
}
}