我试图使用nlm()来最小化函数中的SSE。我在语法和让nlm()为这两个变量提供估计时遇到了困难。最终,t_1、t_2和t_3将是从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语法。对于两个变量,我相信我必须为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.
发布于 2019-12-21 11:52:26
如果您仔细观察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)但是,vector或array都可以工作,但是不能像以前那样给出两个参数。
编辑
在数值优化中,初始点是非常重要的。我建议您使用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 <- ans$estimate[1]Y是:
y <- ans$estimate[2]您还具有一个最优值,即:
ans$minimum :
0.9337047
fun(c(s, y)) :
0.9337047我的第二篇文章,编辑只是为了揭示这样一个事实:使用nlm函数进行优化有点棘手,因为您需要仔细地选择初始值。
optim也是R的一个优化函数,它更稳定,在我给出的例子中有很多初始化点。
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.0res data.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函数只是为了避免循环中断。if是把NA放在正确的地方。
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与nlm之间的关系,您可能会看到他们的。在您的具体案例中,optim似乎是一个更好的选择。我不知道我们能不能概括一下。
https://stackoverflow.com/questions/59435824
复制相似问题