I figured it out. The issue was with my derivative calculation. I was using (a - b) / DELTA * 2. Changing this to (b - a) / DELTA * 2 fixes this problem.
a = morton3pTime(cp - DELTA, wPrime, pmax, p); b = morton3pTime(cp + DELTA, wPrime, pmax, p); jacobian.setEntry(i, 0, (b - a) / (DELTA * 2)); Thanks On Fri, Dec 28, 2018 at 8:33 PM Gilles <gil...@harfang.homelinux.org> wrote: > Hello. > > On Thu, 27 Dec 2018 07:32:30 -0600 (CST), David Tinker wrote: > > Hi Guys. I am struggling to use the least squares optimizer to fit a > > 2 > > variable non-linear function to a curve of observed data points. I am > > pretty > > sure I am doing something stupid because I don't know the maths. My > > MultivariateJacobianFunction moves away from my starting values on > > the first > > iteration but then converges back to the starting values. My > > variables are > > CP and W' and this is what happens: > > > > cp 250.0 W' 24000.0 (starting values) > > cp 197.17292724155843 W' 5627.212534968825 > > cp 233.7927945744999 W' 18662.916420529345 > > cp 245.72618039512386 W' 22592.92114117481 > > cp 248.91747806252718 W' 23643.613738664597 > > cp 249.99999974080222 W' 23999.9999146684 > > ... > > cp 249.99999993520052 W' 23999.99997866709 > > optimum {250; 24,000} > > > > Any ideas? > > What happens when different starting points? > > Gilles > > > Here is the code: > > > > public class LeastSquaresExample { > > > > private static final double DELTA = 0.000001; // for calculating > > derivatives > > > > public static void main(String[] args) { > > Vector2D[] observedPoints = new Vector2D[3]; > > observedPoints[0] = new Vector2D(388, 250); // maps power in > > watts > > to time in seconds > > observedPoints[1] = new Vector2D(368, 450); > > observedPoints[2] = new Vector2D(321, 780); > > > > int pmax = 961; > > > > MultivariateJacobianFunction fn = point -> { > > double cp = point.getEntry(0); > > double wPrime = point.getEntry(1); > > System.out.println("cp " + cp + " W' " + wPrime); > > > > RealVector value = new > > ArrayRealVector(observedPoints.length); > > RealMatrix jacobian = new > > Array2DRowRealMatrix(observedPoints.length, 2); > > for (int i = 0; i < observedPoints.length; i++) { > > double p = observedPoints[i].getX(); > > value.setEntry(i, morton3pTime(cp, wPrime, pmax, p)); > > > > // each row in the jacobian is a measurement and cols > > are > > partial derivatives wrt cp(0) and wPrime(1) > > double a, b; > > a = morton3pTime(cp - DELTA, wPrime, pmax, p); > > b = morton3pTime(cp + DELTA, wPrime, pmax, p); > > jacobian.setEntry(i, 0, (a - b) / (DELTA * 2)); > > > > a = morton3pTime(cp, wPrime - DELTA, pmax, p); > > b = morton3pTime(cp, wPrime + DELTA, pmax, p); > > jacobian.setEntry(i, 1, (a - b) / (DELTA * 2)); > > } > > return new Pair<>(value, jacobian); > > }; > > > > double[] target = new double[observedPoints.length]; > > for (int i = 0; i < observedPoints.length; i++) target[i] = > > observedPoints[i].getY(); > > > > LeastSquaresProblem problem = new LeastSquaresBuilder() > > .start(new double[]{250.0, 24000.0}) > > .model(fn) > > .target(target) > > .maxEvaluations(1000) > > .maxIterations(1000) > > .build(); > > LeastSquaresOptimizer.Optimum optimum = new > > LevenbergMarquardtOptimizer().optimize(problem); > > RealVector pt = optimum.getPoint(); > > System.out.println("optimum " + pt); > > } > > > > private static double morton3pTime(double cp, double wPrime, > > double > > pmax, double p) { > > return wPrime / (p - cp) + wPrime / (cp - pmax); > > } > > } > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: user-unsubscr...@commons.apache.org > For additional commands, e-mail: user-h...@commons.apache.org > >