/*
* RapidMiner
*
* Copyright (C) 2001-2011 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.validation;
import com.rapidminer.example.AttributeWeights;
import com.rapidminer.example.ExampleSet;
import com.rapidminer.operator.Model;
import com.rapidminer.operator.OperatorChain;
import com.rapidminer.operator.OperatorDescription;
import com.rapidminer.operator.OperatorException;
import com.rapidminer.operator.ValueDouble;
import com.rapidminer.operator.learner.CapabilityProvider;
import com.rapidminer.operator.performance.PerformanceCriterion;
import com.rapidminer.operator.performance.PerformanceVector;
import com.rapidminer.operator.ports.InputPort;
import com.rapidminer.operator.ports.OutputPort;
import com.rapidminer.operator.ports.metadata.CapabilityPrecondition;
import com.rapidminer.operator.ports.metadata.Precondition;
import com.rapidminer.operator.ports.metadata.SubprocessTransformRule;
/**
* This operator evaluates the performance of feature weighting algorithms
* including feature selection. The first subprocess contains the algorithm to be
* evaluated itself. It must return an attribute weights vector which is then applied
* on the data. The second subprocess must build and return a new model on this data, which is then
* evaluated during the third subprocess. Hence it must return a performance vector. This
* performance vector serves as a performance indicator for the actual
* algorithm.
*
* @author Ingo Mierswa
*/
public abstract class WrapperValidationChain extends OperatorChain implements CapabilityProvider {
private PerformanceCriterion lastPerformance;
protected InputPort exampleSetInput = getInputPorts().createPort("example set in");
private final OutputPort innerWeightingSetSource = getSubprocess(0).getInnerSources().createPort("weighting set source");
private final InputPort innerAttributeWeightsSink = getSubprocess(0).getInnerSinks().createPort("attribute weights sink", AttributeWeights.class);
private final OutputPort innerTrainSetSource = getSubprocess(1).getInnerSources().createPort("train set source");
private final InputPort innerModelSink = getSubprocess(1).getInnerSinks().createPort("model sink", Model.class);
private final OutputPort innerTestSetSource = getSubprocess(2).getInnerSources().createPort("test set source");
private final OutputPort innerModelSource = getSubprocess(2).getInnerSources().createPort("model source");
private final InputPort innerPerformanceSink = getSubprocess(2).getInnerSinks().createPort("performance vector sink", PerformanceVector.class);
protected OutputPort performanceOutput = getOutputPorts().createPort("performance vector out");
protected OutputPort attributeWeightsOutput = getOutputPorts().createPort("attribute weights out");
public WrapperValidationChain(OperatorDescription description) {
super(description, "Attribute Weighting", "Model Building", "Model Evaluation");
exampleSetInput.addPrecondition(getCapabilityPrecondition());
getTransformer().addPassThroughRule(exampleSetInput, innerWeightingSetSource);
getTransformer().addRule(new SubprocessTransformRule(getSubprocess(0)));
getTransformer().addPassThroughRule(exampleSetInput, innerTrainSetSource);
getTransformer().addRule(new SubprocessTransformRule(getSubprocess(1)));
getTransformer().addPassThroughRule(exampleSetInput, innerTestSetSource);
getTransformer().addPassThroughRule(innerModelSink, innerModelSource);
getTransformer().addRule(new SubprocessTransformRule(getSubprocess(2)));
getTransformer().addPassThroughRule(innerPerformanceSink, performanceOutput);
getTransformer().addPassThroughRule(innerAttributeWeightsSink, attributeWeightsOutput);
addValue(new ValueDouble("performance", "The last performance (main criterion).") {
@Override
public double getDoubleValue() {
if (lastPerformance != null)
return lastPerformance.getAverage();
else
return Double.NaN;
}
});
addValue(new ValueDouble("variance", "The variance of the last performance (main criterion).") {
@Override
public double getDoubleValue() {
if (lastPerformance != null)
return lastPerformance.getVariance();
else
return Double.NaN;
}
});
}
/**
* This method can be overwritten in order to give a more senseful quickfix.
*/
protected Precondition getCapabilityPrecondition() {
return new CapabilityPrecondition(this, exampleSetInput);
}
/**
* Can be used by subclasses to set the performance of the example set. Will
* be used for plotting only.
*/
void setResult(PerformanceCriterion pc) {
lastPerformance = pc;
}
/** Applies the method. */
AttributeWeights useWeightingMethod(ExampleSet methodTrainingSet) throws OperatorException {
innerWeightingSetSource.deliver(methodTrainingSet);
getSubprocess(0).execute();
return innerAttributeWeightsSink.getData();
}
/** Applies the learner. */
Model learn(ExampleSet trainingSet) throws OperatorException {
innerTrainSetSource.deliver(trainingSet);
getSubprocess(1).execute();
return innerModelSink.getData();
}
/** Applies the applier and evaluator. */
PerformanceVector evaluate(ExampleSet testSet, Model model) throws OperatorException {
innerTestSetSource.deliver(testSet);
innerModelSource.deliver(model);
getSubprocess(2).execute();
return innerPerformanceSink.getData();
}
}