gov.sandia.cognition.learning.data.feature.LinearRegressionCoefficientExtractor 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: LinearRegressionBuffer.java
* Authors: Justin Basilico
* Company: Sandia National Laboratories
* Project: Cognitive Foundry
*
* Copyright March 23, 2006, Sandia Corporation. Under the terms of Contract
* DE-AC04-94AL85000, there is a non-exclusive license for use of this work by
* or on behalf of the U.S. Government. Export of this program may require a
* license from the United States Government. See CopyrightHistory.txt for
* complete details.
*
*/
package gov.sandia.cognition.learning.data.feature;
import gov.sandia.cognition.annotation.CodeReview;
import gov.sandia.cognition.math.matrix.VectorFactory;
import gov.sandia.cognition.math.matrix.Vector;
import gov.sandia.cognition.evaluator.AbstractStatefulEvaluator;
import gov.sandia.cognition.collection.FiniteCapacityBuffer;
import gov.sandia.cognition.math.RingAccumulator;
/**
* Takes a sampled sequence of equal-dimension vectors as input and computes
* the linear regression coefficients for each dimension in the vectors. In
* other words, it compute the best-fit equation:
*
* y_i = m*x_i + b,
*
* where "m" and "b" are the slope and offset for that dimension in the buffer.
* For each "i" vector dimension in the regression buffer. Thus, if one puts
* vectors of dimension "n" into the buffer, at each timestep, one will get
* one vector of slopes (m) and one vector of offsets (b), each of dimension n.
* The output of the evaluate() method is a Matrix with first column of slopes,
* and the next column of offsets.
*
* @author Justin Basilico
* @since 1.0
*/
@CodeReview(
reviewer="Kevin R. Dixon",
date="2006-07-17",
changesNeeded=false,
comments={
"Encapsulated members, added a comment to virtually every method and member.",
"Added comment about the regression equation.",
"No additional changes needed."
}
)
public class LinearRegressionCoefficientExtractor
extends AbstractStatefulEvaluator>
{
/**
* Default maximum buffer size, {@value}.
*/
public static final int DEFAULT_MAX_BUFFER_SIZE = 20;
/**
* maximum number of vectors to hold in the buffer
*/
private int maxBufferSize;
/**
* Default constructor.
*/
public LinearRegressionCoefficientExtractor()
{
this( DEFAULT_MAX_BUFFER_SIZE );
}
/**
* Creates new instance of LinearRegressionEvaluator
*
* @param maxBufferSize
* maximum number of vectors to hold in the buffer
*/
public LinearRegressionCoefficientExtractor(
int maxBufferSize )
{
super();
this.setMaxBufferSize( maxBufferSize );
}
@Override
public LinearRegressionCoefficientExtractor clone()
{
LinearRegressionCoefficientExtractor clone =
(LinearRegressionCoefficientExtractor) super.clone();
if( this.getState() != null )
{
clone.setState( this.getState().clone() );
}
return clone;
}
public FiniteCapacityBuffer createDefaultState()
{
return new FiniteCapacityBuffer( this.getMaxBufferSize() );
}
public Vector evaluate(
Vector input )
{
int M = input.getDimensionality();
this.getState().addLast( input );
// This is the mean of the arithmetic series from 0..(num-1):
// 1->0;
// 2->0.5;
// 3->1;
// 4->0+1+2+3->1.5;
// 5->0+1+2+3+4->2;
// Thus, meanx == (num-1) / 2.0;
int num = this.getState().size();
Vector ms;
Vector bs;
RingAccumulator sumy = new RingAccumulator( this.getState() );
Vector meany = sumy.getMean();
if( num > 1 )
{
double meanx = -(num - 1) / 2.0;
double sxx = 0.0;
RingAccumulator sumxy = new RingAccumulator();
int x = -num + 1;
for (Vector y : this.getState())
{
double dx = x - meanx;
sxx += dx * dx;
sumxy.accumulate( y.minus( meany ).scale( dx ) );
x++;
}
ms = sumxy.scaleSum( 1.0/sxx );
bs = meany.minus( ms.scale(meanx) );
}
else
{
ms = VectorFactory.getDefault().createVector(M);
bs = meany;
}
return bs.stack(ms);
}
/**
* Getter for maxBufferSize
* @return
* Maximum Buffer size
*/
public int getMaxBufferSize()
{
return this.maxBufferSize;
}
/**
* Setter for maxBufferSize
* @param maxBufferSize
* Maximum buffer size, must be >= 2
*/
public void setMaxBufferSize(
int maxBufferSize )
{
if (maxBufferSize < 2)
{
throw new IllegalArgumentException(
"Must have at least 2 samples to fit two polynomials!!" );
}
this.maxBufferSize = maxBufferSize;
this.setState(null);
}
}