001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.math.stat.regression; 018 019 import org.apache.commons.math.linear.LUDecompositionImpl; 020 import org.apache.commons.math.linear.RealMatrix; 021 import org.apache.commons.math.linear.Array2DRowRealMatrix; 022 import org.apache.commons.math.linear.RealVector; 023 024 /** 025 * The GLS implementation of the multiple linear regression. 026 * 027 * GLS assumes a general covariance matrix Omega of the error 028 * <pre> 029 * u ~ N(0, Omega) 030 * </pre> 031 * 032 * Estimated by GLS, 033 * <pre> 034 * b=(X' Omega^-1 X)^-1X'Omega^-1 y 035 * </pre> 036 * whose variance is 037 * <pre> 038 * Var(b)=(X' Omega^-1 X)^-1 039 * </pre> 040 * @version $Revision: 1073460 $ $Date: 2011-02-22 20:22:39 +0100 (mar. 22 f??vr. 2011) $ 041 * @since 2.0 042 */ 043 public class GLSMultipleLinearRegression extends AbstractMultipleLinearRegression { 044 045 /** Covariance matrix. */ 046 private RealMatrix Omega; 047 048 /** Inverse of covariance matrix. */ 049 private RealMatrix OmegaInverse; 050 051 /** Replace sample data, overriding any previous sample. 052 * @param y y values of the sample 053 * @param x x values of the sample 054 * @param covariance array representing the covariance matrix 055 */ 056 public void newSampleData(double[] y, double[][] x, double[][] covariance) { 057 validateSampleData(x, y); 058 newYSampleData(y); 059 newXSampleData(x); 060 validateCovarianceData(x, covariance); 061 newCovarianceData(covariance); 062 } 063 064 /** 065 * Add the covariance data. 066 * 067 * @param omega the [n,n] array representing the covariance 068 */ 069 protected void newCovarianceData(double[][] omega){ 070 this.Omega = new Array2DRowRealMatrix(omega); 071 this.OmegaInverse = null; 072 } 073 074 /** 075 * Get the inverse of the covariance. 076 * <p>The inverse of the covariance matrix is lazily evaluated and cached.</p> 077 * @return inverse of the covariance 078 */ 079 protected RealMatrix getOmegaInverse() { 080 if (OmegaInverse == null) { 081 OmegaInverse = new LUDecompositionImpl(Omega).getSolver().getInverse(); 082 } 083 return OmegaInverse; 084 } 085 086 /** 087 * Calculates beta by GLS. 088 * <pre> 089 * b=(X' Omega^-1 X)^-1X'Omega^-1 y 090 * </pre> 091 * @return beta 092 */ 093 @Override 094 protected RealVector calculateBeta() { 095 RealMatrix OI = getOmegaInverse(); 096 RealMatrix XT = X.transpose(); 097 RealMatrix XTOIX = XT.multiply(OI).multiply(X); 098 RealMatrix inverse = new LUDecompositionImpl(XTOIX).getSolver().getInverse(); 099 return inverse.multiply(XT).multiply(OI).operate(Y); 100 } 101 102 /** 103 * Calculates the variance on the beta. 104 * <pre> 105 * Var(b)=(X' Omega^-1 X)^-1 106 * </pre> 107 * @return The beta variance matrix 108 */ 109 @Override 110 protected RealMatrix calculateBetaVariance() { 111 RealMatrix OI = getOmegaInverse(); 112 RealMatrix XTOIX = X.transpose().multiply(OI).multiply(X); 113 return new LUDecompositionImpl(XTOIX).getSolver().getInverse(); 114 } 115 116 117 /** 118 * Calculates the estimated variance of the error term using the formula 119 * <pre> 120 * Var(u) = Tr(u' Omega^-1 u)/(n-k) 121 * </pre> 122 * where n and k are the row and column dimensions of the design 123 * matrix X. 124 * 125 * @return error variance 126 * @since 2.2 127 */ 128 @Override 129 protected double calculateErrorVariance() { 130 RealVector residuals = calculateResiduals(); 131 double t = residuals.dotProduct(getOmegaInverse().operate(residuals)); 132 return t / (X.getRowDimension() - X.getColumnDimension()); 133 134 } 135 136 }