All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hipparchus.stat.regression.RegressionResults Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.hipparchus.stat.regression;

import java.io.Serializable;
import java.util.Arrays;

import org.hipparchus.exception.MathIllegalArgumentException;
import org.hipparchus.util.FastMath;
import org.hipparchus.util.MathUtils;

/**
 * Results of a Multiple Linear Regression model fit.
 *
 */
public class RegressionResults implements Serializable {

    /** INDEX of Sum of Squared Errors */
    private static final int SSE_IDX = 0;
    /** INDEX of Sum of Squares of Model */
    private static final int SST_IDX = 1;
    /** INDEX of R-Squared of regression */
    private static final int RSQ_IDX = 2;
    /** INDEX of Mean Squared Error */
    private static final int MSE_IDX = 3;
    /** INDEX of Adjusted R Squared */
    private static final int ADJRSQ_IDX = 4;
    /** UID */
    private static final long serialVersionUID = 1l;
    /** regression slope parameters */
    private final double[] parameters;
    /** variance covariance matrix of parameters */
    private final double[][] varCovData;
    /** boolean flag for variance covariance matrix in symm compressed storage */
    private final boolean isSymmetricVCD;
    /** rank of the solution */
    @SuppressWarnings("unused")
    private final int rank;
    /** number of observations on which results are based */
    private final long nobs;
    /** boolean flag indicator of whether a constant was included*/
    private final boolean containsConstant;
    /** array storing global results, SSE, MSE, RSQ, adjRSQ */
    private final double[] globalFitInfo;

    /**
     *  Set the default constructor to private access
     *  to prevent inadvertent instantiation
     */
    @SuppressWarnings("unused")
    private RegressionResults() {
        this.parameters = null;
        this.varCovData = null;
        this.rank = -1;
        this.nobs = -1;
        this.containsConstant = false;
        this.isSymmetricVCD = false;
        this.globalFitInfo = null;
    }

    /**
     * Constructor for Regression Results.
     *
     * @param parameters a double array with the regression slope estimates
     * @param varcov the variance covariance matrix, stored either in a square matrix
     * or as a compressed
     * @param isSymmetricCompressed a flag which denotes that the variance covariance
     * matrix is in symmetric compressed format
     * @param nobs the number of observations of the regression estimation
     * @param rank the number of independent variables in the regression
     * @param sumy the sum of the independent variable
     * @param sumysq the sum of the squared independent variable
     * @param sse sum of squared errors
     * @param containsConstant true model has constant,  false model does not have constant
     * @param copyData if true a deep copy of all input data is made, if false only references
     * are copied and the RegressionResults become mutable
     */
    public RegressionResults(
            final double[] parameters, final double[][] varcov,
            final boolean isSymmetricCompressed,
            final long nobs, final int rank,
            final double sumy, final double sumysq, final double sse,
            final boolean containsConstant,
            final boolean copyData) {
        if (copyData) {
            this.parameters = parameters.clone();
            this.varCovData = new double[varcov.length][];
            for (int i = 0; i < varcov.length; i++) {
                this.varCovData[i] = varcov[i].clone();
            }
        } else {
            this.parameters = parameters;
            this.varCovData = varcov;
        }
        this.isSymmetricVCD = isSymmetricCompressed;
        this.nobs = nobs;
        this.rank = rank;
        this.containsConstant = containsConstant;
        this.globalFitInfo = new double[5];
        Arrays.fill(this.globalFitInfo, Double.NaN);

        if (rank > 0) {
            this.globalFitInfo[SST_IDX] = containsConstant ?
                    (sumysq - sumy * sumy / nobs) : sumysq;
        }

        this.globalFitInfo[SSE_IDX] = sse;
        this.globalFitInfo[MSE_IDX] = this.globalFitInfo[SSE_IDX] /
                (nobs - rank);
        this.globalFitInfo[RSQ_IDX] = 1.0 -
                this.globalFitInfo[SSE_IDX] /
                this.globalFitInfo[SST_IDX];

        if (!containsConstant) {
            this.globalFitInfo[ADJRSQ_IDX] = 1.0-
                    (1.0 - this.globalFitInfo[RSQ_IDX]) *
                    ( (double) nobs / ( (double) (nobs - rank)));
        } else {
            this.globalFitInfo[ADJRSQ_IDX] = 1.0 - (sse * (nobs - 1.0)) /
                    (globalFitInfo[SST_IDX] * (nobs - rank));
        }
    }

    /**
     * 

Returns the parameter estimate for the regressor at the given index.

* *

A redundant regressor will have its redundancy flag set, as well as * a parameters estimated equal to {@code Double.NaN}

* * @param index Index. * @return the parameters estimated for regressor at index. * @throws MathIllegalArgumentException if {@code index} is not in the interval * {@code [0, number of parameters)}. */ public double getParameterEstimate(int index) throws MathIllegalArgumentException { if (parameters == null) { return Double.NaN; } MathUtils.checkRangeInclusive(index, 0, this.parameters.length - 1); return this.parameters[index]; } /** *

Returns a copy of the regression parameters estimates.

* *

The parameter estimates are returned in the natural order of the data.

* *

A redundant regressor will have its redundancy flag set, as will * a parameter estimate equal to {@code Double.NaN}.

* * @return array of parameter estimates, null if no estimation occurred */ public double[] getParameterEstimates() { if (this.parameters == null) { return null; } return parameters.clone(); } /** * Returns the standard * error of the parameter estimate at index, * usually denoted s(bindex). * * @param index Index. * @return the standard errors associated with parameters estimated at index. * @throws MathIllegalArgumentException if {@code index} is not in the interval * {@code [0, number of parameters)}. */ public double getStdErrorOfEstimate(int index) throws MathIllegalArgumentException { if (parameters == null) { return Double.NaN; } MathUtils.checkRangeInclusive(index, 0, this.parameters.length - 1); double var = this.getVcvElement(index, index); if (!Double.isNaN(var) && var > Double.MIN_VALUE) { return FastMath.sqrt(var); } return Double.NaN; } /** *

Returns the standard * error of the parameter estimates, * usually denoted s(bi).

* *

If there are problems with an ill conditioned design matrix then the regressor * which is redundant will be assigned Double.NaN.

* * @return an array standard errors associated with parameters estimates, * null if no estimation occurred */ public double[] getStdErrorOfEstimates() { if (parameters == null) { return null; } double[] se = new double[this.parameters.length]; for (int i = 0; i < this.parameters.length; i++) { double var = this.getVcvElement(i, i); if (!Double.isNaN(var) && var > Double.MIN_VALUE) { se[i] = FastMath.sqrt(var); continue; } se[i] = Double.NaN; } return se; } /** *

Returns the covariance between regression parameters i and j.

* *

If there are problems with an ill conditioned design matrix then the covariance * which involves redundant columns will be assigned {@code Double.NaN}.

* * @param i {@code i}th regression parameter. * @param j {@code j}th regression parameter. * @return the covariance of the parameter estimates. * @throws MathIllegalArgumentException if {@code i} or {@code j} is not in the * interval {@code [0, number of parameters)}. */ public double getCovarianceOfParameters(int i, int j) throws MathIllegalArgumentException { if (parameters == null) { return Double.NaN; } MathUtils.checkRangeInclusive(i, 0, this.parameters.length - 1); MathUtils.checkRangeInclusive(j, 0, this.parameters.length - 1); return this.getVcvElement(i, j); } /** *

Returns the number of parameters estimated in the model.

* *

This is the maximum number of regressors, some techniques may drop * redundant parameters

* * @return number of regressors, -1 if not estimated */ public int getNumberOfParameters() { if (this.parameters == null) { return -1; } return this.parameters.length; } /** * Returns the number of observations added to the regression model. * * @return Number of observations, -1 if an error condition prevents estimation */ public long getN() { return this.nobs; } /** *

Returns the sum of squared deviations of the y values about their mean.

* *

This is defined as SSTO * here.

* *

If {@code n < 2}, this returns {@code Double.NaN}.

* * @return sum of squared deviations of y values */ public double getTotalSumSquares() { return this.globalFitInfo[SST_IDX]; } /** *

Returns the sum of squared deviations of the predicted y values about * their mean (which equals the mean of y).

* *

This is usually abbreviated SSR or SSM. It is defined as SSM * here

* *

Preconditions:

    *
  • At least two observations (with at least two different x values) * must have been added before invoking this method. If this method is * invoked before a model can be estimated, Double.NaN is * returned. *

* * @return sum of squared deviations of predicted y values */ public double getRegressionSumSquares() { return this.globalFitInfo[SST_IDX] - this.globalFitInfo[SSE_IDX]; } /** *

Returns the * sum of squared errors (SSE) associated with the regression * model.

* *

The return value is constrained to be non-negative - i.e., if due to * rounding errors the computational formula returns a negative result, * 0 is returned.

* *

Preconditions:

    *
  • numberOfParameters data pairs * must have been added before invoking this method. If this method is * invoked before a model can be estimated, Double,NaN is * returned. *

* * @return sum of squared errors associated with the regression model */ public double getErrorSumSquares() { return this.globalFitInfo[ SSE_IDX]; } /** *

Returns the sum of squared errors divided by the degrees of freedom, * usually abbreviated MSE.

* *

If there are fewer than numberOfParameters + 1 data pairs in the model, * or if there is no variation in x, this returns * Double.NaN.

* * @return sum of squared deviations of y values */ public double getMeanSquareError() { return this.globalFitInfo[ MSE_IDX]; } /** *

Returns the * coefficient of multiple determination, * usually denoted r-square.

* *

Preconditions:

    *
  • At least numberOfParameters observations (with at least numberOfParameters different x values) * must have been added before invoking this method. If this method is * invoked before a model can be estimated, {@code Double,NaN} is * returned. *

* * @return r-square, a double in the interval [0, 1] */ public double getRSquared() { return this.globalFitInfo[ RSQ_IDX]; } /** *

Returns the adjusted R-squared statistic, defined by the formula

     * R2adj = 1 - [SSR (n - 1)] / [SSTO (n - p)]
     * 
* where SSR is the sum of squared residuals}, * SSTO is the total sum of squares}, n is the number * of observations and p is the number of parameters estimated (including the intercept).

* *

If the regression is estimated without an intercept term, what is returned is

     *  1 - (1 - {@link #getRSquared()} ) * (n / (n - p)) 
     * 

* * @return adjusted R-Squared statistic */ public double getAdjustedRSquared() { return this.globalFitInfo[ ADJRSQ_IDX]; } /** * Returns true if the regression model has been computed including an intercept. * In this case, the coefficient of the intercept is the first element of the * {@link #getParameterEstimates() parameter estimates}. * @return true if the model has an intercept term */ public boolean hasIntercept() { return this.containsConstant; } /** * Gets the i-jth element of the variance-covariance matrix. * * @param i first variable index * @param j second variable index * @return the requested variance-covariance matrix entry */ private double getVcvElement(int i, int j) { if (this.isSymmetricVCD) { if (this.varCovData.length > 1) { //could be stored in upper or lower triangular if (i == j) { return varCovData[i][i]; } else if (i >= varCovData[j].length) { return varCovData[i][j]; } else { return varCovData[j][i]; } } else {//could be in single array if (i > j) { return varCovData[0][(i + 1) * i / 2 + j]; } else { return varCovData[0][(j + 1) * j / 2 + i]; } } } else { return this.varCovData[i][j]; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy