[R] Upper limit in nlsLM not working as expected
nashjc at uottawa.ca
nashjc at uottawa.ca
Fri Oct 19 14:50:01 CEST 2012
I think this might be what you want. Kate Mullen and I have been in
correspondence over some edge cases where minpack.LM may not handle bounds
appropriately. However, though nlmrt seems to do the job here, readers
should note that R benefits hugely if we maintain some friendly
competition (and collaboration) to both offer methods with different
performance profiles (e.g., handling different classes/sizes of problems
better) and in
helping to root out bugs. So I want minpack.LM to be there for comparison
and use when itdoes a better job. It should, for example, be much faster.
nlmrt is designed to be aggressive and also modifiable, so that the
algorithm can be explored.
John Nash
library(nlmrt)
#Fit function to data
fitn<-nlxb(y ~ y0 + 2*(A/pi)*w/(4*(x-xc)^2+w^2),
control=nls.lm.control(
factor=100,
maxiter=1024,
ftol = .Machine$double.eps,
ptol = .Machine$double.eps
),
data=data,
na.action=na.exclude,
start=st2,
algorith='LM',
lower=c(-0.0001,-1e-8,0.05,0.2),
#upper=c(1e-6,0.003,0.08,0.35),
upper=c(Inf,Inf,0.07,Inf),
trace=F
)
# > str(fitn)
# List of 6
# $ resid : num [1:151] 0.00265 0.00124 -0.00222 -0.00239 0.00148 ...
# $ jacobian: num [1:151, 1:4] 1 1 1 1 1 1 1 1 1 1 ...
# ..- attr(*, "dimnames")=List of 2
# .. ..$ : NULL
# .. ..$ : chr [1:4] "y0" "A" "w" "xc"
# $ feval : num 24
# $ jeval : num 16
# $ coeffs : num [1:4] 0.00014 0.0099 0.05939 0.22975
# $ ssquares: num 0.000857
On 10/19/2012 06:00 AM, r-help-request at r-project.org wrote:
> Message: 11
> Date: Thu, 18 Oct 2012 12:16:17 +0000
> From: Martin Hehn <Martin.Hehn at postgrad.manchester.ac.uk>
> To: "r-help at R-project.org" <r-help at R-project.org>
> Subject: [R] Upper limit in nlsLM not working as expected
> Message-ID:
> <17F41A7342EEB6409BDA31C3ACDBAC1005AD55 at MBXP07.ds.man.ac.uk>
> Content-Type: text/plain
>
> Dear all,
>
> I am using the nlsLM function to fit a Lorentzian function to my
experimental data.
> The LM algorithm should allow to specify limits, but the upper limit
appears not to work as expected in my code.
> The parameter 'w', which is peak width at half maximuim always hits the
upper limit if the limit is specified. I would expect the value to be
in-between the upper and lower limit with maybe hitting either limit
occasionally.
>
> The code below calculates a lorentzian curve with some noise added that
looks like a typical experimental spectrum. Then a fit is made to this
data. Note that if 'w' in the upper limit is set to e.g 0.6, 0.7, or 0.8
the fit always hits this limit. If 'w'=Inf, the fit calculates to
something around 0.06, which is correct.
>
> Why does the fit go wrong if 'w' is not Inf?
>
> library(minpack.lm)
> #Create x axis
> x<-seq(from=0.1,to=0.6,by=0.5/150)
> #Simulate a function with noise
> fu<-function(y0,A,w,xc,x){
> eq<-y0 + 2*A/pi*w/(4*(x-xc)^2+w^2)
> eq<-jitter(eq,factor=200)
> }
> #Evaluate function aka Measured data
> y<-fu(0,0.01,0.06,0.23,x)
> data<-as.data.frame(cbind(x,y))
>
> #Start values for fitting
> st2<-data.frame(
> y0=0,
> A=0.0001,
> w=0.055,
> xc=0.28
> )
> #Fit function to data
> fit<-nlsLM(y ~ y0 + 2*(A/pi)*w/(4*(x-xc)^2+w^2),
> control=nls.lm.control(
> factor=100,
> maxiter=1024,
> ftol = .Machine$double.eps,
> ptol = .Machine$double.eps
> ),
> data=data,
> na.action=na.exclude,
> start=st2,
> algorith='LM',
> lower=c(-0.0001,-1e-8,0.05,0.2),
> #upper=c(1e-6,0.003,0.08,0.35),
> upper=c(Inf,Inf,0.07,Inf),
> trace=F
> )
> #Predict fitting values
> fity<-predict(fit,data$x)
>
> plot(data$x,data$y)
> lines(data$x,fity,col=2)
> text(0.4,0.08,coef(fit)['y0'])
> text(0.4,0.07,coef(fit)['A'])
> text(0.4,0.06,coef(fit)['w'])
> text(0.4,0.05,coef(fit)['xc'])
>
> Best regard
> Martin
More information about the R-help
mailing list