Made the changes in my copy, will push them along with the changes to make SimpleRegression compliant with the UpdatingMultipleRegression interface.
On Sat, Sep 10, 2011 at 12:29 PM, Greg Sterijevski <gsterijev...@gmail.com>wrote: > Sorry about the formatting. I looked through checkstyle report and my zeal > to eliminate extraneous whitespace was only matched by my need to add > whitespace around arguments!!! > > > On Sat, Sep 10, 2011 at 10:22 AM, Phil Steitz <phil.ste...@gmail.com>wrote: > >> On 9/9/11 9:18 PM, gr...@apache.org wrote: >> > Author: gregs >> > Date: Sat Sep 10 04:18:31 2011 >> > New Revision: 1167451 >> > >> > URL: http://svn.apache.org/viewvc?rev=1167451&view=rev >> > Log: >> > (MATH-649) SimpleRegression needs the ability to suppress the intercept >> >> The plugin was able to pick this up and attach it to the ticket, but >> we usually use the format >> JIRA: MATH-649 >> >> Also, remember to update changes.xml. We usually try to do this in >> the same commit, but we all forget sometimes ;) >> >> Thanks for taking care of this. See one nit below. >> > >> > >> > This commit pushes changes to allow the estimation of the a regression >> in which the intercept is constrained to be zero. I am also pushing two unit >> tests. >> > >> > Modified: >> > >> commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/regression/SimpleRegression.java >> > >> commons/proper/math/trunk/src/test/java/org/apache/commons/math/stat/regression/SimpleRegressionTest.java >> > >> > Modified: >> commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/regression/SimpleRegression.java >> > URL: >> http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/regression/SimpleRegression.java?rev=1167451&r1=1167450&r2=1167451&view=diff >> > >> ============================================================================== >> > --- >> commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/regression/SimpleRegression.java >> (original) >> > +++ >> commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/regression/SimpleRegression.java >> Sat Sep 10 04:18:31 2011 >> > @@ -84,13 +84,23 @@ public class SimpleRegression implements >> > /** mean of accumulated y values, used in updating formulas */ >> > private double ybar = 0; >> > >> > + /** include an intercept or not */ >> > + private final boolean hasIntercept; >> > // ---------------------Public >> methods-------------------------------------- >> > >> > /** >> > * Create an empty SimpleRegression instance >> > */ >> > public SimpleRegression() { >> > + this(true); >> > + } >> > + /** >> > + * Secondary constructor which allows the user the ability to >> include/exclude const >> > + * @param includeIntercept boolean flag, true includes an intercept >> > + */ >> > + public SimpleRegression(boolean includeIntercept){ >> > super(); >> > + hasIntercept = includeIntercept; >> > } >> > >> > /** >> > @@ -106,22 +116,32 @@ public class SimpleRegression implements >> > * @param x independent variable value >> > * @param y dependent variable value >> > */ >> > - public void addData(double x, double y) { >> > + public void addData(final double x, final double y){ >> > if (n == 0) { >> > xbar = x; >> > ybar = y; >> > } else { >> > - double dx = x - xbar; >> > - double dy = y - ybar; >> > - sumXX += dx * dx * (double) n / (n + 1d); >> > - sumYY += dy * dy * (double) n / (n + 1d); >> > - sumXY += dx * dy * (double) n / (n + 1d); >> > - xbar += dx / (n + 1.0); >> > - ybar += dy / (n + 1.0); >> > + if( hasIntercept ){ >> >> We usually don't add the extra spaces around arguments, but do add a >> space before the { >> >> > + final double fact1 = 1.0 + (double) n; >> > + final double fact2 = ((double) n) / (1.0 + (double) n); >> > + final double dx = x - xbar; >> > + final double dy = y - ybar; >> > + sumXX += dx * dx * fact2; >> > + sumYY += dy * dy * fact2; >> > + sumXY += dx * dy * fact2; >> > + xbar += dx / fact1; >> > + ybar += dy / fact1; >> > + } >> > + } >> > + if( !hasIntercept ){ >> > + sumXX += x * x ; >> > + sumYY += y * y ; >> > + sumXY += x * y ; >> > } >> > sumX += x; >> > sumY += y; >> > n++; >> > + return; >> > } >> > >> > >> > @@ -140,17 +160,29 @@ public class SimpleRegression implements >> > */ >> > public void removeData(double x, double y) { >> > if (n > 0) { >> > - double dx = x - xbar; >> > - double dy = y - ybar; >> > - sumXX -= dx * dx * (double) n / (n - 1d); >> > - sumYY -= dy * dy * (double) n / (n - 1d); >> > - sumXY -= dx * dy * (double) n / (n - 1d); >> > - xbar -= dx / (n - 1.0); >> > - ybar -= dy / (n - 1.0); >> > - sumX -= x; >> > - sumY -= y; >> > - n--; >> > + if (hasIntercept) { >> > + final double fact1 = (double) n - 1.0; >> > + final double fact2 = ((double) n) / ((double) n - 1.0); >> > + final double dx = x - xbar; >> > + final double dy = y - ybar; >> > + sumXX -= dx * dx * fact2; >> > + sumYY -= dy * dy * fact2; >> > + sumXY -= dx * dy * fact2; >> > + xbar -= dx / fact1; >> > + ybar -= dy / fact1; >> > + } else { >> > + final double fact1 = (double) n - 1.0; >> > + sumXX -= x * x; >> > + sumYY -= y * y; >> > + sumXY -= x * y; >> > + xbar -= x / fact1; >> > + ybar -= y / fact1; >> > + } >> > + sumX -= x; >> > + sumY -= y; >> > + n--; >> > } >> > + return; >> > } >> > >> > /** >> > @@ -235,7 +267,10 @@ public class SimpleRegression implements >> > */ >> > public double predict(double x) { >> > double b1 = getSlope(); >> > - return getIntercept(b1) + b1 * x; >> > + if (hasIntercept) { >> > + return getIntercept(b1) + b1 * x; >> > + } >> > + return b1 * x; >> > } >> > >> > /** >> > @@ -255,7 +290,16 @@ public class SimpleRegression implements >> > * @return the intercept of the regression line >> > */ >> > public double getIntercept() { >> > - return getIntercept(getSlope()); >> > + return hasIntercept ? getIntercept(getSlope()) : 0.0; >> > + } >> > + >> > + /** >> > + * Returns true if a constant has been included false otherwise. >> > + * >> > + * @return true if constant exists, false otherwise >> > + */ >> > + public boolean hasIntercept(){ >> > + return hasIntercept; >> > } >> > >> > /** >> > @@ -391,7 +435,7 @@ public class SimpleRegression implements >> > if (n < 3) { >> > return Double.NaN; >> > } >> > - return getSumSquaredErrors() / (n - 2); >> > + return hasIntercept ? (getSumSquaredErrors() / (n - 2)) : >> (getSumSquaredErrors() / (n - 1)); >> > } >> > >> > /** >> > @@ -443,11 +487,15 @@ public class SimpleRegression implements >> > * <p> >> > * If there are fewer that <strong>three</strong> observations in >> the >> > * model, or if there is no variation in x, this returns >> > - * <code>Double.NaN</code>.</p> >> > + * <code>Double.NaN</code>.</p> Additionally, a >> <code>Double.NaN</code> is >> > + * returned when the intercept is constrained to be zero >> > * >> > * @return standard error associated with intercept estimate >> > */ >> > public double getInterceptStdErr() { >> > + if( !hasIntercept ){ >> > + return Double.NaN; >> > + } >> > return FastMath.sqrt( >> > getMeanSquareError() * ((1d / (double) n) + (xbar * xbar) / >> sumXX)); >> > } >> > @@ -572,8 +620,11 @@ public class SimpleRegression implements >> > * @param slope current slope >> > * @return the intercept of the regression line >> > */ >> > - private double getIntercept(double slope) { >> > + private double getIntercept(double slope){ >> > + if( hasIntercept){ >> > return (sumY - slope * sumX) / n; >> > + } >> > + return 0.0; >> > } >> > >> > /** >> > >> > Modified: >> commons/proper/math/trunk/src/test/java/org/apache/commons/math/stat/regression/SimpleRegressionTest.java >> > URL: >> http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/stat/regression/SimpleRegressionTest.java?rev=1167451&r1=1167450&r2=1167451&view=diff >> > >> ============================================================================== >> > --- >> commons/proper/math/trunk/src/test/java/org/apache/commons/math/stat/regression/SimpleRegressionTest.java >> (original) >> > +++ >> commons/proper/math/trunk/src/test/java/org/apache/commons/math/stat/regression/SimpleRegressionTest.java >> Sat Sep 10 04:18:31 2011 >> > @@ -80,6 +80,76 @@ public final class SimpleRegressionTest >> > {5, -1 }, {6, 12 } >> > }; >> >> Tests with reference data. Nice! :) >> > >> > + >> > + /* >> > + * Data from NIST NOINT1 >> > + */ >> > + private double[][] noint1 = { >> > + {130.0,60.0}, >> > + {131.0,61.0}, >> > + {132.0,62.0}, >> > + {133.0,63.0}, >> > + {134.0,64.0}, >> > + {135.0,65.0}, >> > + {136.0,66.0}, >> > + {137.0,67.0}, >> > + {138.0,68.0}, >> > + {139.0,69.0}, >> > + {140.0,70.0} >> > + }; >> > + >> > + /* >> > + * Data from NIST NOINT2 >> > + * >> > + */ >> > + private double[][] noint2 = { >> > + {3.0,4}, >> > + {4,5}, >> > + {4,6} >> > + }; >> > + >> > + @Test >> > + public void testNoInterceot_noint2(){ >> > + SimpleRegression regression = new SimpleRegression(false); >> > + regression.addData(noint2[0][1], noint2[0][0]); >> > + regression.addData(noint2[1][1], noint2[1][0]); >> > + regression.addData(noint2[2][1], noint2[2][0]); >> > + Assert.assertEquals("slope", 0.727272727272727, >> > + regression.getSlope(), 10E-12); >> > + Assert.assertEquals("slope std err", 0.420827318078432E-01, >> > + regression.getSlopeStdErr(),10E-12); >> > + Assert.assertEquals("number of observations", 3, >> regression.getN()); >> > + Assert.assertEquals("r-square", 0.993348115299335, >> > + regression.getRSquare(), 10E-12); >> > + Assert.assertEquals("SSR", 40.7272727272727, >> > + regression.getRegressionSumSquares(), 10E-9); >> > + Assert.assertEquals("MSE", 0.136363636363636, >> > + regression.getMeanSquareError(), 10E-10); >> > + Assert.assertEquals("SSE", 0.272727272727273, >> > + regression.getSumSquaredErrors(),10E-9); >> > + } >> > + >> > + @Test >> > + public void testNoIntercept_noint1(){ >> > + SimpleRegression regression = new SimpleRegression(false); >> > + for (int i = 0; i < noint1.length; i++) { >> > + regression.addData(noint1[i][1], noint1[i][0]); >> > + } >> > + Assert.assertEquals("slope", 2.07438016528926, >> regression.getSlope(), 10E-12); >> > + Assert.assertEquals("slope std err", 0.165289256198347E-01, >> > + regression.getSlopeStdErr(),10E-12); >> > + Assert.assertEquals("number of observations", 11, >> regression.getN()); >> > + Assert.assertEquals("r-square", 0.999365492298663, >> > + regression.getRSquare(), 10E-12); >> > + Assert.assertEquals("SSR", 200457.727272727, >> > + regression.getRegressionSumSquares(), 10E-9); >> > + Assert.assertEquals("MSE", 12.7272727272727, >> > + regression.getMeanSquareError(), 10E-10); >> > + Assert.assertEquals("SSE", 127.272727272727, >> > + regression.getSumSquaredErrors(),10E-9); >> > + >> > + } >> > + >> > @Test >> > public void testNorris() { >> > SimpleRegression regression = new SimpleRegression(); >> > >> > >> > >> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org >> For additional commands, e-mail: dev-h...@commons.apache.org >> >> >