Если вы внимательно посмотрите на функцию 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 is:
s <- ans$estimate[1]
y is :
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.0
res 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
кажется лучшим выбором. Я не знаю, можем ли мы немного обобщить.
person
Rémi Coulaud
schedule
21.12.2019