Non linear function parameter estimation - matlab, lsqnonlin, fzero

Andrew Strathclyde picture Andrew Strathclyde · Oct 10, 2012 · Viewed 10k times · Source

I'm having difficulty with a fitting problem. From the errors that I get I imagine that the boundaries are not defined correctly and I haven't managed to find a solution. Any help would be very much appreciated.

Alternative methods for the solution of the same problem are also accepted.

Description

I have to estimate the parameters of a non-linear function of the type:

A*y(x) + B*EXP(C*y(x)) + g(x,D) = 0

subjected to the parameters PAR = [A,B,C,D] being within the range

LB < PAR < UB

Code

To solve the problem I'm using the Matlab functions lsqnonlin and fzero. The simplified code used is reported below.

The problem is divided in four functions:

  1. parameterEstimation - (a wrapper for the lsqnonlin function)
  2. objectiveFunction_lsq - (the objective function for the param estimation)
  3. yFun - (the function returing the value of the variable y)
  4. objectiveFunction_zero - (the objective function of the non-linear equation used to calculate y)

Errors

Running the code on the data I get the this waring

Warning: Length of lower bounds is > length(x); ignoring extra bounds

and this error

Failure in initial user-supplied objective function evaluation. LSQNONLIN cannot continue

This makes me to think that the boundaries are not correctly used or not correctly called, but maybe the problem is elsewhere.


function Done = parameterEstimation()
    %read inputs
    Xmeas = xlsread('filepath','worksheet','range');
    Ymeas = xlsread('filepath','worksheet','range');

    %inital values and boundary conditions
    initialGuess = [1,1,1,1]; %model parameters initial guess
    LB = [0,0,0,0]; %model parameters lower boundaries
    UB = [2,2,2,2]; %model parameters upper boundaries

    %parameter estimation
    calcParam = lsqnonlin(@objectiveFunction_lsq_2,initialGuess,LB,UB,[],Xmeas,Ymeas);
    Done = calcParam;

function diff = objectiveFunction_lsq_2(PAR,Xmeas,Ymeas)
    y_calculated = yFun(PAR,Xmeas);
    diff = y_calculated-Ymeas;

function result = yFun(PAR,X)
    y_0 = 2;
    val = fzero(@(y)objfun_y(y,PAR,X),y_0);
    result = val;

function result = objfun_y(y,PAR,X)
    A = PAR(1);
    B = PAR(2);
    A = PAR(3);
    C = PAR(4);
    D = PAR(5);

    val = A*y+B*exp(y*C)+g(D,X);
    result = val;

Answer

julietKiloRomeo picture julietKiloRomeo · Nov 8, 2012

I don't have the optimization toolbox, but are you sure you can pass the constants like that?

I would do this instead:

calcParam = lsqnonlin(@(PAR) objectiveFunction_lsq_2(PAR,Xmeas,Ymeas),initialGuess,LB,UB);