R: Ошибка в is.nloptr(ret): цель в x0 возвращает NA

Я пытаюсь использовать пакет nloptr, чтобы найти оптимальное значение x, которое максимизирует нелинейную функцию F=b0+b1*x+b2*x^2+b3*x^3.

Я использую следующий код с функцией apply(), чтобы пропустить его через каждую отдельную строку фрейма данных регрессии и получить оптимальное значение функции для каждой отдельной строки:

F <- function(x,b0,b1,b2,b3){return(b0+b1*x+b2*x^2+b3*x^3)}
Optimal <- apply(Regression,1,function(i){
                  nloptr( x0 <- c(0)
                         ,eval_f <- F
                         ,eval_g_ineq = NULL
                         ,eval_g_eq = NULL
                         ,eval_grad_f = NULL
                         ,eval_jac_g_ineq = NULL
                         ,eval_jac_g_eq = NULL
                         ,lb <- c(-Inf)
                         ,ub <- c(Inf)
                         ,opts <- list( "algorithm" = "NLOPT_LD_AUGLAG",
                                        "xtol_rel" = 1.0e-7,
                                        "maxeval" = 1000)
                         ,b0=Regression$b0[i]
                         ,b1=Regression$b1[i]
                         ,b2=Regression$b2[i]
                         ,b3=Regression$b3[i])})

Фрейм данных регрессии, который код вызывает для значений b0, b1, b2, b3, имеет следующий формат:

Tag bo b1 b2 b3
A   5  6  1  3
B   8  8  7  3
C   9  2  7  5
D   1  6  1  3
E   3  6  2  1
..  .. .. .. ..

Я получаю следующую ошибку при запуске скрипта:

Error in is.nloptr(ret) : objective in x0 returns NA
In addition: Warning message:
In if (is.na(f0)) { :

person nba2020    schedule 01.04.2018    source источник


Ответы (1)


Вам НЕ следует передавать строки «Регрессии» с помощью apply, если вы также намереваетесь получить доступ к элементам внутри функции. Также будет проблема, когда apply принуждает Regression к одному типу. Это будет символ, а не число. Вместо этого должно быть:

library(nloptr)
F <- function(x,b0,b1,b2,b3){return(b0+b1*x+b2*x^2+b3*x^3)}
Optimal <- apply(Regression[-1],     #removes first column
                                 1, function(i){   # i-variable gets values
                  nloptr( x0 <- c(0)
                         ,eval_f <- F
                         ,eval_g_ineq = NULL
                         ,eval_g_eq = NULL
                         ,eval_grad_f = NULL
                         ,eval_jac_g_ineq = NULL
                         ,eval_jac_g_eq = NULL
                         ,lb <- c(-Inf)
                         ,ub <- c(Inf)
                         ,opts <- list( "algorithm" = "NLOPT_LD_AUGLAG",
                                        "xtol_rel" = 1.0e-7,
                                        "maxeval" = 1000)
                         ,b0=i[1]
                         ,b1=i[2]
                         ,b2=i[3]
                         ,b3=i[4])})

Протестировано с вашим объектом "Регрессия". (У меня есть опасения по поводу того, будет ли минимум или максимум при попытке работать с кубическим многочленом.) К сожалению, вы выбрали противоречивые параметры:

Error in is.nloptr(ret) : 
  A gradient for the objective function is needed by algorithm NLOPT_LD_AUGLAG 
but was not supplied.

Однако вычислить градиент многочлена можно без особого труда.

После построения функции градиента я теперь получаю:

grad_fun <- function(x,b0,b1,b2,b3) { b1 + x*b2/3 +x^2*b3/3 }
> F <- function(x, b0,b1,b2,b3){return(b0+b1*x+b2*x^2+b3*x^3)}
> Optimal <- apply(Regression[-1],     
+                                  1, function(i){   
+                   nloptr( x0 <- c(0)
+                          ,eval_f <- F
+                          ,eval_g_ineq = NULL
+                          ,eval_g_eq = NULL
+                          ,eval_grad_f = grad_fun
+                          ,eval_jac_g_ineq = NULL
+                          ,eval_jac_g_eq = NULL
+                          ,lb <- c(-Inf)
+                          ,ub <- c(Inf)
+                          ,opts <- list( "algorithm" = "NLOPT_LD_AUGLAG",
+                                         "xtol_rel" = 1.0e-7,
+                                         "maxeval" = 1000)
+                          ,b0=i[1]
+                          ,b1=i[2]
+                          ,b2=i[3]
+                          ,b3=i[4])})
Error in is.nloptr(ret) : 
  The algorithm NLOPT_LD_AUGLAG needs a local optimizer; specify an algorithm and termination condition in local_opts

Мне показалось, что я помог вам преодолеть несколько препятствий, так что это еще не совсем ответ, но он кажется полезным и слишком длинным для комментария.

Редактировать; Дальнейшие эксперименты с изменением алгоритма на "algorithm" = "NLOPT_LD_LBFGS" приводят к тому, что код запускается без ошибок, но, насколько я вижу, 4 запускает весь возвращаемый список с $ message : chr "NLOPT_FAILURE: Generic failure code.". Я предполагаю, что оптимизация кубических полиномов обычно не работает без ограничений, и я не вижу их в вашей спецификации задачи.

person IRTFM    schedule 01.04.2018
comment
Большое спасибо. На самом деле ограничения — это то, что я намеревался добавить после преодоления препятствия, с которым вы успешно мне помогли. Большое спасибо за ваши усилия. Я высоко ценю ваш подробный ответ. - person nba2020; 01.04.2018