Search code examples
javaapache-commonsleast-squares

Least squares Levenburg Marquardt with Apache commons


I'm using the non linear least squares Levenburg Marquardt algorithm in java to fit a number of exponential curves (A+Bexp(Cx)). Although the data is quite clean and has a good approximation to the model the algorithm is not able to model the majority of them even with a excessive number of iterations(5000-6000). For the curves it can model, it does so in about 150 iterations.

LeastSquaresProblem problem = new LeastSquaresBuilder()
        .start(start).model(jac).target(dTarget)
        .lazyEvaluation(false).maxEvaluations(5000)
        .maxIterations(6000).build();

LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer();
LeastSquaresOptimizer.Optimum optimum = optimizer.optimize(problem);}

My question is how would I define a convergence criteria in apache commons in order to stop it hitting a max number of iterations?


Solution

  • I don't believe Java is your problem. Let's address the mathematics.

    This problem is easier to solve if you change your function.

    Your assumed equation is:

    y = A + B*exp(C*x)
    

    It'd be easier if you could do this:

    y-A = B*exp(C*x)
    

    Now A is just a constant that can be zero or whatever value you need to shift the curve up or down. Let's call that variable z:

    z = B*exp(C*x)
    

    Taking the natural log of both sides:

    ln(z) = ln(B*exp(C*x))
    

    We can simplify that right hand side to get the final result:

    ln(z) = ln(B) + C*x
    

    Transform your (x, y) data to (x, z) and you can use least squares fitting of a straight line where C is the slope in (x, z) space and ln(B) is the intercept. Lots of software available to do that.