r和mlrMBO中的噪声优化结果错误

时间:2019-08-08 12:01:12

标签: r optimization bayesian mlr

我有一个嘈杂的优化任务。我试图找到一个函数的参数(选择哪些资产及其权重),以使它们最小化函数结果(跟踪误差-投资组合和指数收益之间的差异)。财务条款对找到解决方案不是很关键。

当我使用mlrMBO中的优化方法时,结果(y)总是与理论结果和直觉结果所期望的相差甚远。 mbo的结果与函数中使用最优参数的结果甚至不同。

我尝试更改学习者,参数集的设置并重新编码该功能,但是它不起作用

这是一个最小的可重现示例(结果是相同的,问题仍然存在,所以我想它是可重现的)

max_stocks <- 10 # maximum number of assets to choose

# for the sake of reproducibility below is a provisional matrix of assets returns, each column is a different asset and stock index returns
quarter.pool <- matrix(rnorm(1830, 0, 0.01), nrow = 61, ncol = 300) 
stock_index <- matrix(rnorm(61,0,0.02))

# function with 2 inputs of same length vectors and tracking error as output
obj_func <- function(stock_weights, which_stocks){

  quarter.pool_ <- quarter.pool[,which_stocks] #choosing which assets to invest in
  portfolio <- matrix(rep(0,nrow(quarter.pool_))) # empty index-tracking portfolio

  for (i in 1:nrow(quarter.pool_)) {
    portfolio[i] <- sum(quarter.pool_[i,]*stock_weights, na.rm = TRUE)}

  tracking_error <- sqrt(sum(portfolio-stock_index)^2/length(portfolio-1))
  return(tracking_error)}

obj_f <- makeSingleObjectiveFunction(name = "index_tracking",
                                     fn = obj_func, 
                                     par.set = makeParamSet( makeNumericVectorParam("stock_weights", len = max_stocks, lower = 0, upper = 0.25),
                                                             makeIntegerVectorParam("which_stocks", len = max_stocks, lower = 1, upper = ncol(quarter.pool))), 
                                     noisy = TRUE, 
                                     vectorized = TRUE)

ctrl <-  makeMBOControl(final.method = "best.true.y", propose.points = 1)
ctrl <- setMBOControlTermination(ctrl, iters = 20, target.fun.value = 0.0000001)

run <- mbo(fun = obj_f, control = ctrl)

obj_func(run$x$stock_weights, run$x$which_stocks) == run$y 
# the result is different even tho function works as usual

无论我在哪里重复脚本,结果都相差很大。 但是主要问题是双重的:

  
      
  1. 它应该接近0,通常甚至不低于0.2。甚至不知道它是否可能。
  2.   
  3. mbo中的“最优” y与将“最优”参数放入同一函数的结果不同。也许是因为y是预测值而不是真实值?虽然差异很大。
  4.   

编辑[1] 显然,当我删除参数“ which_stocks”时,一切都很好,因此一定是因为它。还有什么办法吗?也许算法不能胜任这项艰巨的任务?

1 个答案:

答案 0 :(得分:1)

请参阅我对设置的评论。从技术上讲,它通过将参数作为列表传递并将has.simple.signature = FALSE添加到欺骗包装程序中来工作。

max_stocks <- 10 # maximum number of assets to choose

# for the sake of reproducibility below is a provisional matrix of assets returns, each column is a different asset and stock index returns
quarter.pool <- matrix(rnorm(1830, 0, 0.01), nrow = 61, ncol = 300) 
stock_index <- matrix(rnorm(61,0,0.02))

# function with 2 inputs of same length vectors and tracking error as output
obj_func <- function(x){
  stock_weights = x$stock_weights
  which_stocks = x$which_stocks
  quarter.pool_ <- quarter.pool[,which_stocks] #choosing which assets to invest in
  portfolio <- matrix(rep(0,nrow(quarter.pool_))) # empty index-tracking portfolio

  for (i in 1:nrow(quarter.pool_)) {
    portfolio[i] <- sum(quarter.pool_[i,]*stock_weights, na.rm = TRUE)}

  tracking_error <- sqrt(sum(portfolio-stock_index)^2/length(portfolio-1))
  return(tracking_error)}

obj_f <- makeSingleObjectiveFunction(name = "index_tracking",
                                     fn = obj_func, 
                                     par.set = makeParamSet( makeNumericVectorParam("stock_weights", len = max_stocks, lower = 0, upper = 0.25),
                                                             makeIntegerVectorParam("which_stocks", len = max_stocks, lower = 1, upper = ncol(quarter.pool))), 
                                     noisy = FALSE, 
                                     vectorized = FALSE,
                                     has.simple.signature = FALSE
                                     )

ctrl <-  makeMBOControl(final.method = "best.true.y", propose.points = 1)
ctrl <- setMBOControlTermination(ctrl, iters = 10, target.fun.value = 0.0000001)

run <- mbo(fun = obj_f, control = ctrl)

obj_func(list(stock_weights = run$x$stock_weights, which_stocks = run$x$which_stocks)) == run$y 

发生的事情是stock_weights和which_stocks被unlist()组合成一个向量并传递给您的obj_func,不幸的是,即使第二个参数(which_stocks)也有效未定义,并且第一个向量太长。这应该提醒您,如果函数有些复杂,请务必在函数参数中添加一些可行性检查。您可以使用checkmate包来实现。基本上,您没有优化真正的目标函数。