我正在使用nlsLM {minpack.lm}
查找函数a
的参数b
和myfun
的值,这些值最适合数据集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
设置约束。但它没有多大帮助。有人可以帮我这里或建议一个不同的方法吗?
答案 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包,它为constrOptim
和optim
提供了一个很好的界面,并自动进行必要的转换,但还没有准备好使用它。以下是使用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
获取myfun1
和constrOptim
的解决方案。
log(a)