# Nonlinear fit with constraints in R2012b

4 views (last 30 days)
Niles Martinsen on 22 Sep 2012
Answered: Bhavin Khatri on 9 Oct 2019
Hi
I am running R2012b and doing nonlinear weighted regression as explained here: http://www.mathworks.se/help/stats/examples/weighted-nonlinear-regression.html. In other words, I am using NonLinearModel.fit.
However is there a way to constrain one of the fit parameters to be positive?
Best, Niles.

Star Strider on 22 Sep 2012
Edited: Star Strider on 22 Sep 2012
The Statistics Toolbox functions (such as you referenced in the link) won't let you constrain the parameters but the Optimization Toolbox functions (such as lsqcurvefit) will.
You can do weighted nonlinear regression with lsqcurvefit, using an interim anonymous function. So if the model you have coded as a function and want to fit is called ‘nonlinmodel’, you would normally call it from lsqcurvefit this way:
x = lsqcurvefit(@nonlinmodel,x0,xdata,ydata,lb,ub);
To do weighted nonlinear regression with it, you need to incorporate your weight vector into an anonymous function, and then call the anonymous fiunction from lsqcurvefit:
Weights = 1./(N.*SE.^2);
nonlinmodelW = @(B,t) Weights .* nonlinearmodel(B,t);
x = lsqcurvefit(nonlinmodelW,x0,xdata,ydata,lb,ub);
For ‘Weights’, I used the typical standard errors usually provided, with N being the number of observations used to calculate each of them. This produces inverse-variance weights, the conventional scheme. Note that ‘Weights’ is a vector of the same dimensions as the vector ‘nonlinearmodel’ returns.
When you simulate your function with your estimated parameters to plot with your data, remember to use the anonymous function. It (here ‘nonlinmodelW’) is the function you fitted, not your original ‘nonlinmodel’.
This anonymous function approach will work with both lsqcurvefit and nlinfit. Before weights were added to nlinfit in 2012b, this was the standard way of doing weighted nonlinear regression with both. I've done weighted nonlinear regression using this approach many times with lsqcurvefit in order to take advantage of the parameter constraints.
Zhaorong Wang on 8 Nov 2013
Thanks Star Strider for providing a nice trick to do weighted fitting using the most powerful lsqcurvefit! However, one thing has to be corrected, if you weight the fitting function "nonlinmodel", you have to weight the ydata as well. Because you are minimizing
sum((nonlinmodelW(B,xdata) - ydata).^2),
readers better deal with this carefully, like writing some wrapper function lsqcurvefit_weighted() for lsqcurvefit()
Sarah Garre on 20 Dec 2013
Dear Zhaorong Wang, thanks for putting our attention to this important detail. How do you suggest to make a 'wrapper'?

Sarah Garre on 20 Dec 2013
if I understand it well, it should be enough to manage it like this:
Weights = 1./(N.*SE.^2);
nonlinmodelW = @(B,t) Weights .* nonlinearmodel(B,t);
x = lsqcurvefit(nonlinmodelW,x0,xdata,Weights .* ydata,lb,ub);
Am I right?
Richard Andersson on 15 Apr 2014
Thanks everyone for your insight on this problem. I would just ask that you clarify exactly what the inputs "B" and "t" are.
Star Strider on 15 Apr 2014
Sarah — That looks correct. I haven’t tested it to be sure.
Richeard — The argument B is the vector of parameters (usually termed β in the literature), and t is the independent variable vector, probably time in this example.
The same objective function format works for both lsqcurvefit and nlinfit, but the arguments must be in the (B,t) order.
In the last few versions, nlinfit has the option of a weighted regression. I haven’t needed to use it recently, so I refer you to the documentation.

Bhavin Khatri on 9 Oct 2019
I think by usual maximum likelihood arguments the weights should be
weights = 1./se.^2
not
weights 1./(N.*se.^2).
Intuitively, it doesn't make sense either, since according to the latter, the more observations you have for a particular data point the smaller the weight!
(Of course you can choose whatever weights you want, but assuming Gaussian errors etc..., if you want the maximum likelihood estimate the weights should be the inverse of the standard error.)