2

我正在尝试使用nlm()最小化函数中的 SSE。我在使用它们的语法时遇到了问题,并且无法nlm()为这两个变量提供估计值。最终t_1,t_2t_3将是从 a 中提取的值,data.frame但我只是为它们分配了数字,直到我可以开始nlm()工作。我已经尝试从这些线程那里那里的解决方案,但没有运气:

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 语法尝试了多种方法。有了 2 个变量,我相信我必须为 p 插入一个数组,但是当我尝试过它没有用时。以下这些解决方案均无效:

# 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 比较陌生。

4

1 回答 1

3

如果您仔细查看该nlm功能。它只问一个论点。一种解决方案是:

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对初始点的错误指定不太敏感的功能。

一个想法是这样做,你制作一个包含许多初始点的网格,然后选择一个给你最好结果的网格:

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

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 <- c(10, 1)

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

您可以像这样获得两个参数: s 是:

s <- ans$estimate[1]

是:

y <- ans$estimate[2]

您还具有最佳值,即:

ans$minimum :
0.9337047
fun(c(s, y)) :
0.9337047

我的第二篇文章,编辑只是为了说明nlm函数优化有点棘手,因为您需要仔细选择初始值。

R的optim优化函数也更稳定,就像我给出的带有许多初始化点的示例一样。

expand.grid函数对于获得这样的网格很有用:

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

resdata.frame为您提供不同初始值的最小值。您会看到第一个首字母的值不会给您带来好的结果,nlm但相对稳定optim

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函数只是为了避免循环中断。就是将ifNA 放在正确的位置。

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如果你不需要真正精确的优化,因为它的稳定性。

optim要对vs进行广泛讨论nlm,您可以看看他们的. 在您的具体情况下optim似乎是一个更好的选择。我不知道我们是否可以概括一下。

于 2019-12-21T11:52:26.577 回答