Решатель NLOPTR, не учитывающий ограничение равенства при оптимизации - PullRequest
0 голосов
/ 19 октября 2019

У меня возникают трудности при попытке выполнить нелинейную ограниченную оптимизацию с использованием библиотеки nloptr.

Мне нужно минимизировать отрицательную логарифмическую функцию правдоподобия линейной комбинации связки в форме

Clayton_t_gumbel = weight1 * clayton_copula + weight2 * gumbel_copula + weight3 * t_copula 

Эта проблема аналогична описанной в статье Бернарда Пфафику «Моделирование финансовых рисков и оптимизация портфеля» вR, глава 9: смеси копул, но с добавлением ограничения равенства весов копул. У меня проблема в том, что оптимизация не учитывает мое ограничение равенства (heq).

Код целевой функции выглядит следующим образом:

LLCG <- function(params,x, copC, copG, copt){ #log likelihood minimization
slot(copC, "parameters") <- params[1]
slot(copG, "parameters") <- params[2]
slot(copt, "parameters") <- params[3:4] #t copula uses two parameters
pi1 <- params[5]  #weight parameters
pi2 <- params[6]
pi3 <- params[7]
#pi3 <- params[6]
opt <- log(pi1 * copula::dCopula(x, copC) + pi2 * copula::dCopula(x, copG)
             + pi3 * copula::dCopula(x, copt)) 
  if(any(is.infinite(opt)))
  {
    opt[which(is.infinite(opt))]<-0
  }
  sum(opt)
}

Где params - это векторпараметры связок и веса линейных комбинаций (pi1, pi2, pi3).

. Мое ограничение равенства (сумма весов = 1):

heq <- function(params, x, copC, copG, copt){
constrain <- c(0*params[1]+ 0*params[2] + 0*params[3] + 
               0*params[4] + params[5] + params[6] + params[7] - 1)
return constrain
}

Где params [5: 7] - это веса, которые должны быть равны 1.

Поскольку я не знаю градиентмоей целевой функции, я подумал об использовании решателя NLOPT_GN_ISRES. Он свободен от производных и поддерживает ограничения равенства в дополнение к границам параметров.

Мой код оптимизации выглядит следующим образом:


## Initializing copula objects
copt <- copula::tCopula(param = 0.5, dim = 8) 
copC <- copula::claytonCopula(2, dim = 8) # delta= 2
copG <- copula::gumbelCopula(2, dim = 8)  # theta= 2

##parameters bounds: some of them are Infinite. The last three are weights between [0,1]
lower <- c(copC@param.lowbnd, 1.1, -0.9,2.1, 0,0,0)  
upper <- c(copC@param.upbnd, copG@param.upbnd, 1,100, 1,1,1) 

##obtaining ecdfs
v<-as.matrix(do.call(cbind, X[[i]]))
U<-v[,1:8]

## Creating copula objects initial guesses
par1 <- copula::fitCopula(copC, U, "itau",estimate.variance= T)@estimate #inversion of Kendall's tau
par2 <- copula::fitCopula(copG, U,"itau", estimate.variance= T)@estimate
par3 <- copula::fitCopula(copt, U,"mpl",estimate.variance= F)@estimate ###mpl 
par4 <- 0.2 ##weight parameters
par5 <- 0.2
par6 <- 0.2

##optimization:
opts <- list("algorithm"="NLOPT_GN_ISRES",
             "xtol_rel"=1.0e-4, 
             "maxeval"=100000, 
             "print_level" = 3, 
             "tol_constraints_eq" = 1.0e-6 )

opt <- nloptr::nloptr(x0 = c(par1, par2, par3, par4, par5,par6), 
                           eval_f = LLCG, x = U, 
                           copC = copC, copG = copG, copt=copt, 
                           lb = lower, ub = upper,
                           eval_g_eq = heq, 
                           opts = opts)

По неизвестной мне причине решатель, вероятнее всего, оценит хорошие параметры связок (из предыдущего опыта), но веса нетронуты. Если я начну с весов = 0,2 каждый, они получат одинаковое значение. Ниже приведен пример оценки параметров. Понятно, что ограничение равенства не выполняется, так как сумма весов = 0,6.

[1] 1.2850078 1.6963797 0.1292916 4.7089477 0.2000000 0.2000000 0.2000000

Я также с радостью принимаю различные решения для nlopters. Спасибо.

...