gov.sandia.cognition.learning.algorithm.InputOutputTransformedBatchLearner Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cognitive-foundry Show documentation
Show all versions of cognitive-foundry Show documentation
A single jar with all the Cognitive Foundry components.
/*
* File: InputOutputTransformedLearner.java
* Authors: Justin Basilico
* Project: Cognitive Foundry
*
* Copyright 2011 Cognitive Foundry. All rights reserved.
*/
package gov.sandia.cognition.learning.algorithm;
import gov.sandia.cognition.evaluator.CompositeEvaluatorTriple;
import gov.sandia.cognition.evaluator.Evaluator;
import gov.sandia.cognition.evaluator.IdentityEvaluator;
import gov.sandia.cognition.evaluator.ReversibleEvaluator;
import gov.sandia.cognition.learning.algorithm.baseline.ConstantLearner;
import gov.sandia.cognition.learning.data.DatasetUtil;
import gov.sandia.cognition.learning.data.DefaultInputOutputPair;
import gov.sandia.cognition.learning.data.DefaultWeightedInputOutputPair;
import gov.sandia.cognition.learning.data.InputOutputPair;
import gov.sandia.cognition.learning.data.WeightedInputOutputPair;
import gov.sandia.cognition.util.ObjectUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* An adapter class for performing supervised learning from data where both
* the input and output have to be transformed before they are passed to the
* learning algorithm. The typical use-case for this class is to make use of
* some supervised learning algorithm on data that does not directly fit its
* input and/or output types. Thus, the data must be transformed before the
* learner is run on the data. It must also be transformed when the resulting
* evaluator is applied to new data. Since both the inputs and outputs need
* to be converted, unsupervised learning algorithms are to be provided to
* learn those transforms from the collection of inputs and outputs,
* respectively. While the input learner just needs to be an evaluator to
* forward-transform the data, the output learner needs to be reversible so
* that the training labels can be reversed from values that the supervised
* learner can be trained on. Thus, the forward evaluation is used during
* training reverse evaluation of the output, while the reverse is used when
* applying it to new data. The result of this learning adapter is the triple
* containing the learned input, supervised, and output evaluators, which can
* be applied to the same data types that the adapter was given in training.
*
* Note that this class can also be used in cases where only one side needs
* to be converted, either by using the static {@code create} methods, or by
* passing in {@code ConstantLearner}s that contain
* {@code IdentityEvaluator}s. Thus, this class can act as a very flexible
* adapter for many types of supervised learning problems.
*
* @param
* The input type of the data to learn on. This is passed into the
* unsupervised learner for the input transform to create the evaluator
* that will then produce the {@code TransformedInputType}.
* @param
* The output type of the input transformer, which will be used as the
* input values to train the (middle) supervised learner.
* @param
* The input type of the output transformer, which will be used as the
* output values to train the (middle) supervised learner. It will be
* the output type of the output transformer (and input type of its
* reverse).
* @param
* The output type of the data to learn on. This is passed into the
* unsupervised learner for the output transform to create the reversible
* data converter for mapping the {@code OutputType} to the
* {@code TransformedOutputType}, or vice-versa.
* @author Justin Basilico
* @since 3.3.3
*/
public class InputOutputTransformedBatchLearner
extends AbstractBatchLearnerContainer>, ? extends Evaluator super TransformedInputType, ? extends TransformedOutputType>>>
implements SupervisedBatchLearner>
{
/** The unsupervised learning algorithm for creating the input
* transformation. */
protected BatchLearner super Collection extends InputType>, ? extends Evaluator super InputType, ? extends TransformedInputType>> inputLearner;
/** The unsupervised learning algorithm for creating the output
* transformation, which must be reversible for evaluation. */
protected BatchLearner super Collection extends OutputType>, ? extends ReversibleEvaluator> outputLearner;
/**
* Creates a new, empty {@code InputOutputTransformedBatchLearner}.
*/
public InputOutputTransformedBatchLearner()
{
this(null, null, null);
}
/**
* Creates a new {@code InputOutputTransformedBatchLearner} with the given
* learners.
*
* @param inputLearner
* The unsupervised learning algorithm for creating the input
* transformation.
* @param learner
* The supervised learner whose input and output are being
* adapted.
* @param outputLearner
* The unsupervised learning algorithm for creating the
* output transformation, which must be reversible for evaluation.
*/
public InputOutputTransformedBatchLearner(
final BatchLearner super Collection extends InputType>, ? extends Evaluator super InputType, ? extends TransformedInputType>> inputLearner,
final BatchLearner super Collection extends InputOutputPair extends TransformedInputType, TransformedOutputType>>, ? extends Evaluator super TransformedInputType, ? extends TransformedOutputType>> learner,
final BatchLearner super Collection extends OutputType>, ? extends ReversibleEvaluator> outputLearner)
{
super(learner);
this.setInputLearner(inputLearner);
this.setOutputLearner(outputLearner);
}
@Override
public InputOutputTransformedBatchLearner clone()
{
@SuppressWarnings("unchecked")
final InputOutputTransformedBatchLearner clone =
(InputOutputTransformedBatchLearner)
super.clone();
clone.inputLearner = ObjectUtil.cloneSafe(this.inputLearner);
clone.outputLearner = ObjectUtil.cloneSafe(this.outputLearner);
return clone;
}
/**
* Learn by first calling the input transformation learner on all the
* input values and the output transformation on the output values. After
* these are created, the adapted supervised data is constructed by
* applying the learned input transformation to each input and the learned
* output transformation to each output. The third (middle) learner is then
* trained on the transformed supervised learning problem.
*
* @param data
* The training data.
* @return
* The composite evaluator triple that applies the input transform,
* the learned function, and then the output transform.
*/
@Override
public CompositeEvaluatorTriple learn(
final Collection extends InputOutputPair extends InputType, OutputType>> data)
{
// First learn the input transformer.
final List originalInputs = DatasetUtil.inputsList(data);
final Evaluator super InputType, ? extends TransformedInputType> inputTransformer =
this.inputLearner.learn(originalInputs);
// Now learn the output transformer and get its reverse.
final List originalOutputs = DatasetUtil.outputsList(data);
final ReversibleEvaluator outputTransformer =
this.outputLearner.learn(originalOutputs);
final Evaluator super TransformedOutputType, ? extends OutputType> outputReverseTransfomer =
outputTransformer.reverse();
// Now transform all the data.
final ArrayList> transformedData =
new ArrayList>(data.size());
for (InputOutputPair extends InputType, OutputType> originalExample : data)
{
final TransformedInputType transformedInput = inputTransformer.evaluate(
originalExample.getInput());
final TransformedOutputType transformedOutput = outputTransformer.evaluate(
originalExample.getOutput());
// Create the transformed input-output pair.
// TODO: We could put in a factory for input-output pairs to special-case this
// type of transform.
if (originalExample instanceof WeightedInputOutputPair, ?>)
{
// Handle weighted examples.
transformedData.add(DefaultWeightedInputOutputPair.create(
transformedInput, transformedOutput,
DatasetUtil.getWeight(originalExample)));
}
else
{
// Unweighted data.
transformedData.add(DefaultInputOutputPair.create(
transformedInput, transformedOutput));
}
}
// Finally, learn the real learner.
final Evaluator super TransformedInputType, ? extends TransformedOutputType> learned =
this.learner.learn(transformedData);
return CompositeEvaluatorTriple.create(
inputTransformer, learned, outputReverseTransfomer);
}
/**
* Gets the unsupervised learning algorithm for creating the input
* transformation.
*
* @return
* The input transformation learner.
*/
public BatchLearner super Collection extends InputType>, ? extends Evaluator super InputType, ? extends TransformedInputType>> getInputLearner()
{
return this.inputLearner;
}
/**
* Sets the unsupervised learning algorithm for creating the input
* transformation.
*
* @param inputLearner
* The input transformation learner.
*/
public void setInputLearner(
final BatchLearner super Collection extends InputType>, ? extends Evaluator super InputType, ? extends TransformedInputType>> inputLearner)
{
this.inputLearner = inputLearner;
}
/**
* Gets the unsupervised learning algorithm for creating the
* output transformation, which must be reversible for evaluation.
*
* @return
* The output transformation learner.
*/
public BatchLearner super Collection extends OutputType>, ? extends ReversibleEvaluator> getOutputLearner()
{
return this.outputLearner;
}
/**
* Gets the unsupervised learning algorithm for creating the
* output transformation, which must be reversible for evaluation.
*
* @param outputLearner
* The output transformation learner.
*/
public void setOutputLearner(
final BatchLearner super Collection extends OutputType>, ? extends ReversibleEvaluator> outputLearner)
{
this.outputLearner = outputLearner;
}
/**
* Creates a new {@code InputOutputTransformedBatchLearner} from the
* three learners.
*
* @param
* The input type of the data to learn on. This is passed into the
* unsupervised learner for the input transform to create the evaluator
* that will then produce the {@code TransformedInputType}.
* @param
* The output type of the input transformer, which will be used as the
* input values to train the (middle) supervised learner.
* @param
* The input type of the output transformer, which will be used as the
* output values to train the (middle) supervised learner. It will be
* the output type of the output transformer.
* @param
* The output type of the data to learn on. This is passed into the
* unsupervised learner for the output transform to create the reversible
* data converter for mapping the {@code OutputType} to the
* {@code TransformedOutputType} to the, or vice-versa.
* @param inputLearner
* The unsupervised learning algorithm for creating the input
* transformation.
* @param learner
* The supervised learner whose input and output are being
* adapted.
* @param outputLearner
* The unsupervised learning algorithm for creating the output
* transformation, which must be reversible for evaluation.
* @return
* A new input-output transformed batch learner.
*/
public static InputOutputTransformedBatchLearner create(
final BatchLearner super Collection extends InputType>, ? extends Evaluator super InputType, ? extends TransformedInputType>> inputLearner,
final BatchLearner super Collection extends InputOutputPair extends TransformedInputType, TransformedOutputType>>, ? extends Evaluator super TransformedInputType, ? extends TransformedOutputType>> learner,
final BatchLearner super Collection extends OutputType>, ? extends ReversibleEvaluator> outputLearner)
{
return new InputOutputTransformedBatchLearner(
inputLearner, learner, outputLearner);
}
/**
* Creates a new {@code InputOutputTransformedBatchLearner} from the
* input and supervised learners, performing no transformation on the
* output type.
*
* @param
* The input type of the data to learn on. This is passed into the
* unsupervised learner for the input transform to create the evaluator
* that will then produce the {@code TransformedInputType}.
* @param
* The output type of the input transformer, which will be used as the
* input values to train the (middle) supervised learner.
* @param
* The output type of the data to learn on. It will be used as the
* output values to train the (middle) supervised learner.
* @param inputLearner
* The unsupervised learning algorithm for creating the input
* transformation.
* @param learner
* The supervised learner whose input is being adapted.
* @return
* A new input transformed batch learner.
*/
public static InputOutputTransformedBatchLearner createInputTransformed(
final BatchLearner super Collection extends InputType>, ? extends Evaluator super InputType, ? extends TransformedInputType>> inputLearner,
final BatchLearner super Collection extends InputOutputPair extends TransformedInputType, OutputType>>, ? extends Evaluator super TransformedInputType, ? extends OutputType>> learner)
{
return create(inputLearner, learner,
new IdentityEvaluator());
}
/**
* Creates a new {@code InputOutputTransformedBatchLearner} from the
* supervised and output learners, performing no transformation on the
* input type.
*
* @param
* The input type of the data to learn on. It will be used as the
* input values to train the (middle) supervised learner.
* @param
* The input type of the output transformer, which will be used as the
* output values to train the (middle) supervised learner. It will be
* the output type of of the output transformer.
* @param
* The output type of the data to learn on. This is passed into the
* unsupervised learner for the output transform to create the reversible
* data converter for mapping the {@code OutputType} to the
* {@code TransformedOutputType} to the, or vice-versa.
* @param learner
* The supervised learner whose output is being adapted.
* @param outputLearner
* The unsupervised learning algorithm for creating the output
* transformation, which must be reversible for evaluation.
* @return
* A new output transformed batch learner.
*/
public static InputOutputTransformedBatchLearner createOutputTransformed(
final BatchLearner super Collection extends InputOutputPair extends InputType, TransformedOutputType>>, ? extends Evaluator super InputType, ? extends TransformedOutputType>> learner,
final BatchLearner super Collection extends OutputType>, ? extends ReversibleEvaluator> outputLearner)
{
return create(new IdentityEvaluator(),
learner, outputLearner);
}
/**
* Creates a new {@code InputOutputTransformedBatchLearner} from the
* predefined input and output transforms and the supervised learner.
*
* @param
* The input type of the data to learn on. This is passed into the
* input transform to produce the {@code TransformedInputType}.
* @param
* The output type of the input transformer, which will be used as the
* input values to train the (middle) supervised learner.
* @param
* The input type of the output transformer, which will be used as the
* output values to train the (middle) supervised learner. It will be
* the output type of the output transformer.
* @param
* The output type of the data to learn on. This is passed into the
* reversible output data converter for mapping the {@code OutputType}
* to the {@code TransformedOutputType} to the, or vice-versa.
* @param inputTransform
* The predefined input transformation.
* @param learner
* The supervised learner whose input and output are being
* adapted.
* @param outputTransform
* The predefined output transformation.
* @return
* A new input-output transformed batch learner.
*/
public static InputOutputTransformedBatchLearner create(
final Evaluator super InputType, ? extends TransformedInputType> inputTransform,
final BatchLearner super Collection extends InputOutputPair extends TransformedInputType, TransformedOutputType>>, ? extends Evaluator super TransformedInputType, ? extends TransformedOutputType>> learner,
final ReversibleEvaluator outputTransform)
{
return create(
ConstantLearner.create(inputTransform), learner,
ConstantLearner.create(outputTransform));
}
/**
* Creates a new {@code InputOutputTransformedBatchLearner} from the
* predefined input transform and the supervised learner. It uses no
* output transformation.
*
* @param
* The input type of the data to learn on. This is passed into the
* input transform to produce the {@code TransformedInputType}.
* @param
* The output type of the input transformer, which will be used as the
* input values to train the (middle) supervised learner.
* @param
* The output type of the data to learn on. It will be used as the
* output values to train the (middle) supervised learner.
* @param inputTransform
* The predefined input transformation.
* @param learner
* The supervised learner whose input and output are being
* adapted.
* @return
* A new input transformed batch learner.
*/
public static InputOutputTransformedBatchLearner createInputTransformed(
final Evaluator super InputType, ? extends TransformedInputType> inputTransform,
final BatchLearner super Collection extends InputOutputPair extends TransformedInputType, OutputType>>, ? extends Evaluator super TransformedInputType, ? extends OutputType>> learner)
{
return create(inputTransform, learner,
new IdentityEvaluator());
}
/**
* Creates a new {@code InputOutputTransformedBatchLearner} from the
* predefined output transforms and the supervised learner. It uses no
* input transformation.
*
* @param
* The input type of the data to learn on. It will be used as the
* input values to train the (middle) supervised learner.
* @param
* The input type of the output transformer, which will be used as the
* output values to train the (middle) supervised learner. It will be
* the output type of of the output transformer.
* @param
* The output type of the data to learn on. This is passed into the
* reversible output data converter for mapping the {@code OutputType}
* to the {@code TransformedOutputType} to the, or vice-versa.
* @param learner
* The supervised learner whose input and output are being
* adapted.
* @param outputTransform
* The predefined output transformation.
* @return
* A new output transformed batch learner.
*/
public static InputOutputTransformedBatchLearner createOutputTransformed(
final BatchLearner super Collection extends InputOutputPair extends InputType, TransformedOutputType>>, ? extends Evaluator super InputType, ? extends TransformedOutputType>> learner,
final ReversibleEvaluator outputTransform)
{
return create(new IdentityEvaluator(),
learner, outputTransform);
}
/**
* Creates a new {@code InputOutputTransformedBatchLearner} from the
* unsupervised input transform learner, supervised learners, and output
* transform.
*
* @param
* The input type of the data to learn on. This is passed into the
* unsupervised learner for the input transform to create the evaluator
* that will then produce the {@code TransformedInputType}.
* @param
* The output type of the input transformer, which will be used as the
* input values to train the (middle) supervised learner.
* @param
* The input type of the output transformer, which will be used as the
* output values to train the (middle) supervised learner. It will be
* the output type of the output transformer.
* @param
* The output type of the data to learn on. This is passed into the
* reversible output data converter for mapping the {@code OutputType}
* to the {@code TransformedOutputType} to the, or vice-versa.
* @param inputLearner
* The unsupervised learning algorithm for creating the input
* transformation.
* @param learner
* The supervised learner whose input and output are being
* adapted.
* @param outputTransform
* The predefined output transformation.
* @return
* A new input-output transformed batch learner.
*/
public static InputOutputTransformedBatchLearner create(
final BatchLearner super Collection extends InputType>, ? extends Evaluator super InputType, ? extends TransformedInputType>> inputLearner,
final BatchLearner super Collection extends InputOutputPair extends TransformedInputType, TransformedOutputType>>, ? extends Evaluator super TransformedInputType, ? extends TransformedOutputType>> learner,
final ReversibleEvaluator outputTransform)
{
return create(inputLearner, learner,
ConstantLearner.create(outputTransform));
}
/**
* Creates a new {@code InputOutputTransformedBatchLearner} from the
* input transform, supervised learner, and unsupervised output transform
* learner.
*
* @param
* The input type of the data to learn on. This is passed into the
* input transform to produce the {@code TransformedInputType}.
* @param
* The output type of the input transformer, which will be used as the
* input values to train the (middle) supervised learner.
* @param
* The input type of the output transformer, which will be used as the
* output values to train the (middle) supervised learner. It will be
* the output type of of the output transformer.
* @param
* The output type of the data to learn on. This is passed into the
* unsupervised learner for the output transform to create the reversible
* data converter for mapping the {@code OutputType} to the
* {@code TransformedOutputType} to the, or vice-versa.
* @param inputTransform
* The predefined input transformation.
* @param learner
* The supervised learner whose input and output are being
* adapted.
* @param outputLearner
* The unsupervised learning algorithm for creating the output
* transformation, which must be reversible for evaluation.
* @return
* A new input-output transformed batch learner.
*/
public static InputOutputTransformedBatchLearner create(
final Evaluator super InputType, ? extends TransformedInputType> inputTransform,
final BatchLearner super Collection extends InputOutputPair extends TransformedInputType, TransformedOutputType>>, ? extends Evaluator super TransformedInputType, ? extends TransformedOutputType>> learner,
final BatchLearner super Collection extends OutputType>, ? extends ReversibleEvaluator> outputLearner)
{
return create(ConstantLearner.create(inputTransform),
learner, outputLearner);
}
}