首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R中具有多变量的nlm

R中具有多变量的nlm
EN

Stack Overflow用户
提问于 2019-12-21 11:35:16
回答 1查看 1.7K关注 0票数 2

我试图使用nlm()来最小化函数中的SSE。我在语法和让nlm()为这两个变量提供估计时遇到了困难。最终,t_1t_2t_3将是从data.frame中提取出来的值,但我只是给它们分配了编号,直到能够使nlm()工作为止。我尝试了这些线程那里那里的解决方案,但没有成功:

代码语言:javascript
复制
t_1 <- 1.91
t_2 <- 3.23
t_3 <- 4.20

fun <- function(s,y){
  (10 - s*(t_1-y + y*exp(-t_1/y)))^2+
    (20 - s*(t_2-y + y*exp(-t_2/y)))^2+
    (30 - s*(t_3-y + y*exp(-t_3/y)))^2
}

## Testing the function
fun(9.57,1.13)
[1] 0.9342627

我尝试过多种方法来实现nlm语法。对于两个变量,我相信我必须为p插入一个数组,但是当我尝试时,它没有工作。以下这些解决办法都没有奏效:

代码语言:javascript
复制
# Attempt 1
p = array(c( 1,0), dim=c(2,1) ) 
ans <- nlm(fun, p)

# Attempt 2
ans <- nlm(fun, c( 0.1, 0.1))

# The first two return a "Error in f(x, ...) : argument "y" is missing, with no default"
# Attempt 3 returns a "invalid function value in 'nlm' optimizer" error

ans <- nlm(fun, c( 0.1, 0.1), y = c(1,1))

我确信我的代码中有几个错误,但我不确定在哪里。这个任务比我以前尝试的要复杂得多,因为我对R.

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-21 11:52:26

如果您仔细观察nlm函数。它只要求一个论点。一个解决办法是:

代码语言:javascript
复制
fun <- function(x){
  s <- x[1]
  y <- x[2]
  (10 - s*(t_1-y + y*exp(-t_1/y)))^2+
    (20 - s*(t_2-y + y*exp(-t_2/y)))^2+
    (30 - s*(t_3-y + y*exp(-t_3/y)))^2
}

p <- array(c(0.4, 0.4), dim = c(2, 1))
# p <- c(0.4, 0.4)
ans <- nlm(f = fun, p = p)

但是,vectorarray都可以工作,但是不能像以前那样给出两个参数。

编辑

在数值优化中,初始点是非常重要的。我建议您使用optim函数,它对初始点的错误说明不太敏感。

一个想法是这样做,你做了一个网格的许多初始点,你选择一个给你最好的结果:

代码语言:javascript
复制
initialisation <- expand.grid(seq(1, 3, 0.5),
                              seq(1, 3, 0.5))
res <- data.frame(optim = rep(0, nrow(initialisation)),
                  nlm = rep(0, nrow(initialisation)))

for(i in 1:nrow(initialisation)){
  res[i, 1] <- optim(as.numeric(initialisation[i, ]), fun)$value
  res[i, 2] <- try(nlm(f = fun, p = as.numeric(initialisation[i, ]))$minimum, silent = T)
}
res

我坚持使用上面的例子,optim函数实际上更稳定。如果您没有其他约束,我建议您使用它。

您可以通过?nlm检查函数参数。

希望能帮上忙。

编辑2

代码语言:javascript
复制
fun <- function(x){
  s <- x[1]
  y <- x[2]
  (10 - s*(t_1-y + y*exp (-t_1/y)))^2+
    (20 - s*(t_2-y + y*exp(-t_2/y)))^2+
    (30 - s*(t_3-y + y*exp(-t_3/y)))^2
}

我选择这个起始点是因为它看起来更接近最优的点。

代码语言:javascript
复制
p <- c(10, 1)

ans <- nlm(f = fun, p = p)

您可以获得如下所示的两个参数:

代码语言:javascript
复制
s <- ans$estimate[1]

Y是:

代码语言:javascript
复制
y <- ans$estimate[2]

您还具有一个最优值,即:

代码语言:javascript
复制
ans$minimum :
0.9337047
fun(c(s, y)) :
0.9337047

我的第二篇文章,编辑只是为了揭示这样一个事实:使用nlm函数进行优化有点棘手,因为您需要仔细地选择初始值。

optim也是R的一个优化函数,它更稳定,在我给出的例子中有很多初始化点。

expand.grid函数对于获得如下网格非常有用:

代码语言:javascript
复制
initialisation <- expand.grid(s = seq(2, 3, 0.5),
                                y = seq(2, 3, 0.5))

initialisation :

   s   y
1 2.0 2.0
2 2.5 2.0
3 3.0 2.0
4 2.0 2.5
5 2.5 2.5
6 3.0 2.5
7 2.0 3.0
8 2.5 3.0
9 3.0 3.0

res data.frame为您提供具有不同首字母值的最小获取值。您可以看到,第一个首字母值对于nlm并没有给出好的结果,但是对于optim则相对稳定。

代码语言:javascript
复制
res <- data.frame(optim = rep(0, nrow(initialisation)),
                  nlm = rep(0, nrow(initialisation)))

for(i in 1:nrow(initialisation)){
  res[i, 1] <- optim(as.numeric(initialisation[i, ]), fun)$value
  res[i, 2] <- if(is.numeric(try(nlm(f = fun, p = as.numeric(initialisation[i, ]))$minimum, silent = T)) == T){
    round(nlm(f = fun, p = as.numeric(initialisation[i, ]))$minimum, 8)
  }else{
    NA
  }
}

try函数只是为了避免循环中断。if是把NA放在正确的地方。

代码语言:javascript
复制
res :
optim         nlm
1 0.9337094        <NA>
2 0.9337058  0.93370468
3 0.9337054        <NA>
4 0.9337101  0.93370468
5 0.9337125 61.18166446
6 0.9337057  0.93370468
7 0.9337120  0.93370468
8 0.9337080  0.93370468
9 0.9337114  0.93370468

当存在NA值时,这意味着nlm由于初始化而不能正常工作。我建议您选择optim,如果您不需要真正精确的优化,因为它的稳定性。

为了深入讨论optimnlm之间的关系,您可能会看到他们的。在您的具体案例中,optim似乎是一个更好的选择。我不知道我们能不能概括一下。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59435824

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档