Search code examples
rfunctionoptimizationbayesian

R: Only length-1 columns are recycled


I am working with R. I am trying to follow the example from this page (https://cran.r-project.org/web/packages/ParBayesianOptimization/vignettes/functionMaximization.html) on optimization - I tried to make a new example for a function with "multiple inputs".

For example:

#load necessary library
library(ParBayesianOptimization)

#define function to be optimized
bayesian_function <- function(x1, x2, x3, x4) {
    var_1 <- sin(x1 + x2)
    var_2 <- cos(x1 - x2)
    var_3 <- x1 + x4
    var_4 <- x3 + x4 -7
    goal = sum(var_1 + var_2 + var_3 + var_4)

    return(goal)

}

}


FUNwrapper <- function(x1,x2,x3,x4) list(
    "Score"=bayesian_function(x1=x1,
                              x2=x2,
                              x3=x3,
                              x4=x4)
)

#specify bounds
bounds <- list(x1 =c(20,40), x2 = c(30,45), x3 = c(10,20), x4 = c(10,50))

#run optimization algorithm
optObj <- bayesOpt(
    FUN = FUNwrapper
    , bounds = bounds
    , initPoints = 10
    , acq = "ei"
    , iters.n = 2
    , gsPoints = 25
)

When I look at the output for this example, it is indicated that the optimization algorithm did not converge:

Running initial scoring function 10 times in 1 thread(s)...  2.71 seconds


Starting Epoch 3 
  1) Fitting Gaussian Process...
  2) Running local optimum search...
     - Convergence Not Found. Trying again with tighter parameters...        0.5 seconds
  3) Running FUN 1 times in 1 thread(s)...  0.28 seconds

Therefore, I tried to increase the number of iterations so that the algorithm might be able to find a better point:

#increase the number of iterations
optObj <- bayesOpt(
    FUN = bayesian_function
    , bounds = bounds
    , initPoints = 1000
    , acq = "ei"
    , iters.n = 10
    , gsPoints = 25
)

But this produces the following error:

Running initial scoring function 1000 times in 1 thread(s)...  359 seconds
Error in rbindlist(scoreSummary) : 
  Column 2 of item 1 is length 6 inconsistent with column 1 which is length 100. Only length-1 columns are recycled.

Does anyone know why this error is being produced? Is it because the function has been iterated too many times?

Thanks


Solution

  • I'm not sure if your error is because of your R version, in my case it is 4.1.0.

    I run your code and it has an issue.

    #load necessary library
    library(ParBayesianOptimization)
    
    #define function to be optimized
    bayesian_function <- function(x1, x2, x3, x4) {
        var_1 <- sin(x1 + x2)
        var_2 <- cos(x1 - x2)
        var_3 <- x1 + x4
        var_4 <- x3 + x4 -7
        goal = sum(var_1 + var_2 + var_3 + var_4)
    
        return(goal)
    }
    

    You wrote another bracket in here that doesn't match, so I removed it.

    FUNwrapper <- function(x1,x2,x3,x4) list(
        "Score"=bayesian_function(x1=x1,
                                  x2=x2,
                                  x3=x3,
                                  x4=x4)
    )
    
    #specify bounds
    bounds <- list(x1 =c(20,40), x2 = c(30,45), x3 = c(10,20), x4 = c(10,50))
    
    #run optimization algorithm
    optObj <- bayesOpt(
        FUN = FUNwrapper
        , bounds = bounds
        , initPoints = 10
        , acq = "ei"
        , iters.n = 2
        , gsPoints = 25
    )
    

    Results are as follows:

    Running initial scoring function 10 times in 1 thread(s)...  0.92 seconds
    
    Starting Epoch 1 
      1) Fitting Gaussian Process...
      2) Running local optimum search...        0.97 seconds
      3) Running FUN 1 times in 1 thread(s)...  0.15 seconds
    
    Starting Epoch 2 
      1) Fitting Gaussian Process...
      2) Running local optimum search...        0.5 seconds
      3) Running FUN 1 times in 1 thread(s)...  0.13 seconds
    

    As you can see, in my case the algorithm converged. You should check your libraries. Let me share my environment.

    attached base packages:
    [1] stats     graphics  grDevices utils     datasets  methods   base     
    
    other attached packages:
    [1] DiceKriging_1.6.0             ParBayesianOptimization_1.2.4
    
    loaded via a namespace (and not attached):
     [1] zip_2.2.0         Rcpp_1.0.7        cellranger_1.1.0  pillar_1.6.1     
     [5] compiler_4.1.0    ggpubr_0.4.0      lhs_1.1.1         forcats_0.5.1    
     [9] iterators_1.0.13  tools_4.1.0       lifecycle_1.0.0   tibble_3.1.2     
    [13] gtable_0.3.0      pkgconfig_2.0.3   rlang_0.4.11      openxlsx_4.2.4   
    [17] foreach_1.5.1     curl_4.3.2        haven_2.4.1       rio_0.5.27       
    [21] dplyr_1.0.7       hms_1.1.0         generics_0.1.0    vctrs_0.3.8      
    [25] grid_4.1.0        tidyselect_1.1.1  glue_1.4.2        data.table_1.14.0
    [29] R6_2.5.0          rstatix_0.7.0     fansi_0.5.0       readxl_1.3.1     
    [33] foreign_0.8-81    carData_3.0-4     ggplot2_3.3.5     purrr_0.3.4      
    [37] tidyr_1.1.3       car_3.0-11        magrittr_2.0.1    scales_1.1.1     
    [41] backports_1.2.1   codetools_0.2-18  ellipsis_0.3.2    abind_1.4-5      
    [45] colorspace_2.0-2  ggsignif_0.6.2    utf8_1.2.1        stringi_1.6.2    
    [49] munsell_0.5.0     broom_0.7.8       crayon_1.4.1      dbscan_1.1-8     
    

    About your question of how do I know if the algorithm converge:

    getBestPars(optObj)
    
    > getBestPars(optObj)
    $x1
    [1] 40
    
    $x2
    [1] 45
    
    $x3
    [1] 20
    
    $x4
    [1] 50
    

    Let’s run the process for a little longer:

    optObjv1 <- addIterations(optObj,iters.n=3,verbose=0)
    getBestPars(optObjv1)
    
    $x1
    [1] 40
    
    $x2
    [1] 45
    
    $x3
    [1] 20
    
    $x4
    [1] 50
    

    The global optimum didn't change even we increased the number of iterations.

    Take a look at this reference: https://github.com/AnotherSamWilson/ParBayesianOptimization