使用约束来使用nlsLM()

时间:2017-06-18 12:36:41

标签: r constraints nls

我正在使用nlsLM {minpack.lm}查找函数a的参数bmyfun的值,这些值最适合数据集mydata

mydata=data.frame(x=c(0,5,9,13,17,20),y = c(0,11,20,29,38,45))

myfun=function(a,b,r,t){
  prd=a*b*(1-exp(-b*r*t))
  return(prd)
}

并使用nlsLM

myfit=nlsLM(y~myfun(a,b,r=2,t=x),data=mydata,start=list(a=2000,b=0.05),
                  lower = c(1000,0), upper = c(3000,1))

有效。但是现在我想介绍一个a*b<1000的约束。我查看nlsLM中可用的选项,通过nls.lm.control设置约束。但它没有多大帮助。有人可以帮我这里或建议一个不同的方法吗?

2 个答案:

答案 0 :(得分:6)

据我所知,在minpack.lm包的nlsLM中,下限和上限参数是唯一可用的约束。
解决问题的一种可能方法是使用包nloptr,一个用于非线性优化的免费开源库 NLopt 的R接口。
在下面的代码中,我使用cobyla,一种非线性不等式和等式约束的无导数优化算法:

mydata <- data.frame(x=c(0,5,9,13,17,20), y=c(0,11,20,29,38,45))

myfun=function(a,b,r,t){
  prd=a*b*(1-exp(-b*r*t))
  return(prd)
}

library(nloptr)

sse <- function(ab,r,x,y){
   sum((y - myfun(ab[1],ab[2],r,x))^2)
}

nonlincons <- function(ab,r,x,y) {
   h <- numeric(1)
   h[1] <-  1000 - ab[1]*ab[2]
   return(h)
}

x0 <- c(2000,0.05)
optpar <- cobyla(x0=x0, fn=sse, lower = c(1000,0), upper = c(3000,1), 
                 hin=nonlincons, r=2, x=mydata$x, y=mydata$y, 
                 control = list(xtol_rel = 1e-12, maxeval = 20000))
(optpar <- optpar$par)

sum((mydata$y-myfun(optpar[1],optpar[2],r=2,mydata$x))^2)

最佳参数的值为:

[1] 3.000000e+03 2.288303e-02

和平方误差之和为:

[1] 38.02078

希望它可以帮到你。

答案 1 :(得分:2)

似乎nlsLM不接受约束,一种可能的方法是使用constrOptim函数,但缺点是您必须将问题转换为{{1}的形式接受。顺便说一句,我目前正在开发一个R包,它为constrOptimoptim提供了一个很好的界面,并自动进行必要的转换,但还没有准备好使用它。以下是使用constrOptim解决此问题的方法。

第一步是constrOptim只接受线性约束, constrOptim =&gt; a * b < 1000,因此您需要使用log(a) + log(b) < log(1000)log(a)重新解决问题,约束条件变为:log(b)-log(a) - log(b) > -log(1000)log(a) >= log(1000),{{ 1}},-log(a) >= -log(3000)-log(b) >= 0是这些约束的矩阵形式。 ui是您的函数的重新参数化版本,然后您可以使用ci获取myfun1constrOptim的解决方案。

log(a)