//
//  OpenForecast - open source, general-purpose forecasting package.
//  Copyright (C) 2002-2011  Steven R. Gould
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

package net.sourceforge.openforecast.models;


import java.util.Enumeration;
import java.util.Iterator;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

import net.sourceforge.openforecast.DataPoint;
import net.sourceforge.openforecast.DataSet;


/**
 * Implements a multiple variable linear regression model using the variables
 * named in the constructor as the independent variables, or the variables
 * passed into one of the init methods. The cofficients of the regression, as
 * well as the accuracy indicators are determined from the data set passed to
 * init.
 *
 * 

Once initialized, this model can be applied to another data set using * the forecast method to forecast values of the dependent variable based on * values of the dependent variable (the one named in the constructor). * *

A multiple variable linear regression model essentially attempts to put * a hyperplane through the data points. Mathematically, assuming the * independent variables are xi and the dependent variable is y, * then this hyperplane can be represented as: *

y = a0 + a1*x1 + a2*x2 + a3*x3 + ...
* where the ai are the coefficients of the regression. The * coefficient a0 is also referred to as the intercept. If all * xi were zero (theoretically at least), it is the forecast value * of the dependentVariable, y. * @author Steven R. Gould * @since 0.2 */ public class MultipleLinearRegressionModel extends AbstractForecastingModel { /** * The intercept for the linear regression model. Initialized following a * call to init. */ private double intercept = 0.0; /** * An mapping of variable names to coefficients for this multiple variable * linear regression model. These are initialized following a call to init. */ private Hashtable coefficient; /** * A default constructor that constructs a new multiple variable Linear * regression model. When this constructor is used, it is assumed that all * independent variables in the DataSet or list of coefficients passed to * init are to be used in the model. To narrow down and explicitly define * what independent variables to use in the model, use the alternate form * of the constructor. * *

For a valid model to be constructed, you should call either * implementation of init. * @see #init(DataSet) * @see #init(double,Hashtable) */ public MultipleLinearRegressionModel() { coefficient = null; } /** * Constructs a new multiple variable linear regression model, using the * given array of names as the independent variables to use. For a valid * model to be constructed, you should call init and pass in a data set * containing a series of data points involving the given independent * variables. * @param independentVariable an array of names of the independent * variables to use in this model. * @see #init(DataSet) * @see #init(double,Hashtable) */ public MultipleLinearRegressionModel( String[] independentVariable ) { setIndependentVariables( independentVariable ); } /** * Initializes the coefficients to use for this regression model. The * coefficients are derived so as to give the best fit hyperplane for the * given data set. * *

Additionally, the accuracy indicators are calculated based on this * data set. * @param dataSet the set of observations to use to derive the regression * coefficients for this model. */ public void init( DataSet dataSet ) { String varNames[] = dataSet.getIndependentVariables(); // If no coefficients have been defined for this model, // use all that exist in this data set if ( coefficient == null ) setIndependentVariables( varNames ); int n = varNames.length; double a[][] = new double[n+1][n+2]; // Iterate through dataSet Iterator it = dataSet.iterator(); while ( it.hasNext() ) { // Get next data point DataPoint dp = it.next(); // For each row in the matrix, a for ( int row=0; row 0 ) { // Get value of independent variable, col String colVarName = varNames[col-1]; colMult = dp.getIndependentValue(colVarName); } a[row][col] += rowMult * colMult; } } } // Solve equations to derive coefficients double coeff[] = Utils.GaussElimination( a ); // Assign coefficients to independent variables intercept = coeff[0]; for ( int i=1; iIn addition to the coefficients, you must also specify the * constant term - or the "intercept" - to use in the regression model. * *

Note that since this method does not require a data set, it is * not possible to calculate the values of the accuracy indicators. * Therefore these are all set to their worse-case values. * @param intercept the constant term - or the "intercept" - to use in * the regression model. * @param coefficients the coefficients to be assigned for use in this * regression model. * @throws ModelNotInitializedException if a coefficient does not exist * in the given Hashtable of coefficients for one or more of the * independent variables used when constructing this model. * @throws ClassCastException if the "value" associated with one of the * coefficients cannot be cast to a Number. */ public void init( double intercept, Hashtable coefficients ) { // If no coefficients have been defined for this model, // use all that exist in the list of coefficients if ( coefficient == null ) { // Iterate through the set of keys, building a String[] Enumeration keysEnum = coefficients.keys(); String[] keys = new String[ coefficients.size() ]; int k = 0; while ( keysEnum.hasMoreElements() ) keys[k++] = keysEnum.nextElement(); setIndependentVariables( keys ); } this.intercept = intercept; // Iterate through the variable names in this.coefficient Iterator it = coefficient.keySet().iterator(); while ( it.hasNext() ) { // Get variable name String name = it.next(); // Look up variable in coefficients Hashtable double coeff = ((Number)coefficients.get(name)).doubleValue(); // Assign value back into this.coefficient coefficient.put( name, new Double(coeff) ); } // Indicate that the model has been initialized initialized = true; // Note that accuracy indicators by default are initialized to // their worst possible values, so no need to update them here } /** * Returns the intercept that will be used by the current model. This * could be a user-defined value or internally calculated depending on * which of the init methods was used to initialize the model. * @return the intercept that will be used by this model. * @throws ModelNotInitializedException if this method is called before * the model has been initialized with a call to init. */ public double getIntercept() { if ( !initialized ) throw new ModelNotInitializedException(); return intercept; } /** * Returns a Hashtable containing the coefficients that will be used by * the current model. These could be user-defined coefficients or * internally calculated coefficients depending on which of the init * methods were used to initialize the model. * *

Note that modifying the coefficients in the Hashtable returned from * this method will not modify the coefficients used by the model. If you * want to modify the coefficients used in the model, then use the * {@link #init(double,Hashtable)} method to re-initialize the model. * @return a Hashtable containing the coefficients that will be used by * this model. * @throws ModelNotInitializedException if this method is called before * the model has been initialized with a call to init. */ public Hashtable getCoefficients() { if ( !initialized ) throw new ModelNotInitializedException(); return new Hashtable( coefficient ); } /** * Returns the number of predictors used by the underlying model. * @return the number of predictors used by the underlying model. */ public int getNumberOfPredictors() { return coefficient.size(); } /** * Using the current model parameters (initialized in init), apply the * forecast model to the given data point. The data point must have valid * values for the independent variables. Upon return, the value of the * dependent variable will be updated with the forecast value computed for * that data point. * @param dataPoint the data point for which a forecast value (for the * dependent variable) is required. * @return the forecast value of the dependent variable for the given data * point. * @throws ModelNotInitializedException if forecast is called before the * model has been initialized with a call to init. */ public double forecast( DataPoint dataPoint ) { if ( !initialized ) throw new ModelNotInitializedException(); double forecastValue = intercept; Iterator< Map.Entry > it = coefficient.entrySet().iterator(); while ( it.hasNext() ) { Map.Entry entry = it.next(); // Get value of independent variable double x = dataPoint.getIndependentValue( (String)entry.getKey() ); // Get coefficient for this variable double coeff = ((Double)entry.getValue()).doubleValue(); forecastValue += coeff * x; } dataPoint.setDependentValue( forecastValue ); return forecastValue; } /** * A helper function that initializes the set of independent variables used * in this model to the given array of independent variable names. * @param independentVariable an array of independent variables to use in * this MultipleLinearRegressionModel. */ private void setIndependentVariables(String[] independentVariable) { // Create a new hashtable of just the right size coefficient = new Hashtable( independentVariable.length ); // Add each independent variable with an initial coefficient of 0.0 for ( int v=0; v TOLERANCE ) desc += "+" + coeff + "*" + entry.getKey(); // else coeff == 0.0 } return desc; } } // Local variables: // tab-width: 4 // End:

Ads help maintain this website.