【问题标题】:R Error: Optimization resulting in "unused argument(x)"R错误:优化导致“未使用的参数(x)”
【发布时间】:2021-10-09 04:26:42
【问题描述】:

我正在使用 R 编程语言。我定义了以下函数,并尝试在此函数上执行“随机搜索”算法。

首先,我加载了库:

#load library : https://cran.r-project.org/web/packages/randomsearch/index.html 

library(randomsearch)

然后,我定义了函数:

# create some data for this example
a1 = rnorm(1000,100,10)
b1 = rnorm(1000,100,10)
c1 = sample.int(1000, 1000, replace = TRUE)
train_data = data.frame(a1,b1,c1)


#define function (4 inputs x[1], x[2], x[3], x[4] and 4 outputs f1, f2, f3, f4)

fn <- function(i) {
    x1 <- x[i,1]; x2 <- x[i,2]; x3 <- x[i,3] ; x4 <- x[i,4]
    f <- numeric(4)
    #bin data according to random criteria
    train_data <- train_data %>%
        mutate(cat = ifelse(a1 <= x1 & b1 <= x3, "a",
                            ifelse(a1 <= x2 & b1 <= x4, "b", "c")))
    
    train_data$cat = as.factor(train_data$cat)
    
    #new splits
    a_table = train_data %>%
        filter(cat == "a") %>%
        select(a1, b1, c1, cat)
    
    b_table = train_data %>%
        filter(cat == "b") %>%
        select(a1, b1, c1, cat)
    
    c_table = train_data %>%
        filter(cat == "c") %>%
        select(a1, b1, c1, cat)
    
    
    #calculate  quantile ("quant") for each bin
    
    table_a = data.frame(a_table%>% group_by(cat) %>%
                             mutate(quant = ifelse(c1 > 150,1,0 )))
    
    table_b = data.frame(b_table%>% group_by(cat) %>%
                             mutate(quant = ifelse(c1 > 300,1,0 )))
    
    table_c = data.frame(c_table%>% group_by(cat) %>%
                             mutate(quant = ifelse(c1 > 400,1,0 )))
    
    f1 = mean(table_a$quant)
    f2 = mean(table_b$quant)
    f3 = mean(table_c$quant)
    
    
    #group all tables
    
    final_table = rbind(table_a, table_b, table_c)
    # calculate the total mean : this is what needs to be optimized
    
    f4 = mean(final_table$quant)
    
    #add some constraints
    if((x3 - x1) < 0. | (x4 - x2) < 0.) {
        f[1] <- NaN
        f[2] <- NaN
        f[3] <- NaN
        f[4] <- NaN
        
    }
    
    return (f)
}

最后,我尝试在这个函数上运行“随机搜索”算法:

#run algorithm
res = randomsearch(fn, lower = c(80, 80, 80, 80), upper = c(100,120,100,120), minimize = c(TRUE, TRUE, TRUE, TRUE), max.evals = 30)
rs = summary(res)

但这导致了以下错误:

fun(x, ...) 中的错误:未使用的参数 (x)

有谁知道为什么会产生这个错误?是否与我定义函数“fn”的方式有关?

谢谢

【问题讨论】:

  • 函数的一个直接问题是不知道x 是什么,因此不知道x[i,j] 是什么。 x 没有作为输入提供,但也没有在函数中创建,所以你的函数将在第一行失败。
  • @Sam Rogers:谢谢您的回复!我已经编写了同一函数的不同版本,希望其中一个定义可以工作。如果您愿意,我可以向您展示我定义此函数的其他一些方法吗?
  • 除此之外,randomsearch() 的运行方式将使调试函数的问题变得困难。我建议先确保您的函数使用来自randomsearch() 的预期输入,然后再在randomsearch() 中使用它。
  • 是的,如果您愿意,欢迎您添加更多函数示例,但我怀疑它们会遇到同样的问题。我将添加一个更详细的答案,可能会对您有所帮助,并随时发布后续问题。

标签: r function search optimization


【解决方案1】:

正如我在 cmets 中提到的,我不完全确定您的目标是什么,或者您要解决什么问题,所以我所做的只是优化您的代码已经写好了。如果我自己从头开始编写,我完全有可能编写非常相似的代码,或者可能会非常不同。

我添加了一个注释版本,以便您可以看到我所做的事情,以及一个删除了不需要的代码的简化版本。根据您的最终目标,可能仍然可以减少最小版本的行数,也可能加快速度,但它们可能不是重要的考虑因素。

我在这种情况下使用的一个基本原则是,运行不必要的代码或保存不使用的东西是没有意义的。

评论版本

library(randomsearch)
library(tidyverse)

# create some data for this example
a1 = rnorm(1000,100,10)
b1 = rnorm(1000,100,10)
c1 = sample.int(1000, 1000, replace = TRUE)
train_data = data.frame(a1,b1,c1)

fun_2  <- function(x) {
    # x1 <- x[1]    # Storing these as additional variables doesn't help at all
    # x2 <- x[2]    # They are only used to bin the data
    # x3 <- x[3] 
    # x4 <- x[4] 
    
    #bin data according to random criteria
    train_data <- train_data %>%
        mutate(cat = ifelse(a1 <= x[1] & b1 <= x[3], "a",
                            ifelse(a1 <= x[2] & b1 <= x[4], "b", "c")))
    
    train_data$cat = as.factor(train_data$cat)
    
    #new splits
    a_table = train_data %>%
        filter(cat == "a") #%>%
    # select(a1, b1, c1, cat) # There are no other columns to select, so this is not needed
    
    b_table = train_data %>%
        filter(cat == "b") #%>%
    # select(a1, b1, c1, cat) 
    
    c_table = train_data %>%
        filter(cat == "c") #%>%
    # select(a1, b1, c1, cat)
    
    #calculate  quantile ("quant") for each bin
    # table_a = data.frame(a_table %>% group_by(cat)    # We don't need another variable for this
                         # %>% mutate(quant = ifelse(c1 > 200,1,0 )))   
    a_table$quant = ifelse(a_table$c1 > 200, 1, 0)  # It can also be simlpified
    
    # table_b = data.frame(b_table%>% group_by(cat) %>%
                             # mutate(quant = ifelse(c1 > 300,1,0 )))
    b_table$quant = ifelse(b_table$c1 > 300, 1, 0)
    
    # table_c = data.frame(c_table%>% group_by(cat) %>%
                             # mutate(quant = ifelse(c1 > 400,1,0 )))
    c_table$quant = ifelse(c_table$c1 > 400, 1, 0)
    
    # f1 = mean(a_table$quant)
    # f2 = mean(b_table$quant)
    # f3 = mean(c_table$quant)

    #group all tables
    
    # final_table = rbind(table_a, table_b, table_c)    # This is not used
    # calculate the total mean : this is what needs to be optimized
    
    # f4 = mean(final_table$quant)  # This is not used
    
    return(c(mean(a_table$quant), mean(b_table$quant), mean(c_table$quant)))
}

精简版

fun_2  <- function(x) {
    #bin data according to random criteria
    train_data <- train_data %>%
        mutate(cat = factor(ifelse(a1 <= x[1] & b1 <= x[3], "a",
                            ifelse(a1 <= x[2] & b1 <= x[4], "b", "c"))))
    
    train_data$cat = as.factor(train_data$cat)
    
    #new splits
    a_table = train_data %>% filter(cat == "a") 
    b_table = train_data %>% filter(cat == "b") 
    c_table = train_data %>% filter(cat == "c") 
    
    #calculate  quantile ("quant") for each bin
    a_table$quant = ifelse(a_table$c1 > 200, 1, 0) 
    b_table$quant = ifelse(b_table$c1 > 300, 1, 0)
    c_table$quant = ifelse(c_table$c1 > 400, 1, 0)
 
    return(c(mean(a_table$quant), mean(b_table$quant), mean(c_table$quant)))
}

不幸的是,它们不会产生相同的结果,但我相信这是由于搜索的随机性,而不是代码中的错误。

希望对您有所帮助。有时间我会看看你的其他问题。

【讨论】:

    【解决方案2】:

    以下代码有效,但我无法使约束工作:

    library(randomsearch)
    
    # create some data for this example
    a1 = rnorm(1000,100,10)
    b1 = rnorm(1000,100,10)
    c1 = sample.int(1000, 1000, replace = TRUE)
    train_data = data.frame(a1,b1,c1)
    
    fun_1  <- function(x) {
        x1 <- x[1]
        x2 <- x[2]
        x3 <- x[3] 
        x4 <- x[4] 
        
        
        #bin data according to random criteria
        train_data <- train_data %>%
            mutate(cat = ifelse(a1 <= x1 & b1 <= x3, "a",
                                ifelse(a1 <= x2 & b1 <= x4, "b", "c")))
        
        train_data$cat = as.factor(train_data$cat)
        
        #new splits
        a_table = train_data %>%
            filter(cat == "a") %>%
            select(a1, b1, c1, cat)
        
        b_table = train_data %>%
            filter(cat == "b") %>%
            select(a1, b1, c1, cat)
        
        c_table = train_data %>%
            filter(cat == "c") %>%
            select(a1, b1, c1, cat)
        
        
        #calculate  quantile ("quant") for each bin
        
        table_a = data.frame(a_table%>% group_by(cat) %>%
                                 mutate(quant = ifelse(c1 > 200,1,0 )))
        
        table_b = data.frame(b_table%>% group_by(cat) %>%
                                 mutate(quant = ifelse(c1 > 300,1,0 )))
        
        table_c = data.frame(c_table%>% group_by(cat) %>%
                                 mutate(quant = ifelse(c1 > 400,1,0 )))
        
        f1 = mean(table_a$quant)
        f2 = mean(table_b$quant)
        f3 = mean(table_c$quant)
        
        
        #group all tables
        
        final_table = rbind(table_a, table_b, table_c)
        # calculate the total mean : this is what needs to be optimized
        
        f4 = mean(final_table$quant)
        
        
        
        return(c(f1, f2,f3))
    }
        
    
    res = randomsearch(fun_1, lower = c(90, 100, 90, 100), upper = c(100,120,100,120), minimize = c(TRUE, TRUE,TRUE), max.evals = 30)
    rs = summary(res)
    

    现在,查看结果:

    > head(rs)
    $pareto.front
             y_1       y_2       y_3       x1       x2       x3       x4
    1  0.7605634 0.6851628 0.6400000 91.12101 114.1228 96.77341 117.0649
    4  0.7611940 0.6974249 0.5867238 90.16010 110.6879 99.06183 103.1964
    5  0.7631579 0.6996337 0.5863570 93.49183 103.2529 90.54579 100.0828
    8  0.7804878 0.7196653 0.5791667 93.37388 101.6645 91.03374 100.0605
    9  0.7878788 0.6862745 0.5936842 92.85005 106.4595 94.16650 105.3454
    14 0.7884615 0.6828423 0.6010782 94.17298 106.6873 91.62018 109.2036
    

    @Sam Rogers:我很想知道你的想法是什么?

    谢谢!

    【讨论】:

    • 很好的解决了你自己的问题!请注意train_data。如果它发生变化或不可用,您的功能将失败。将它作为显式输入添加到函数会更安全,或者如果它总是相同的东西,那么在函数中生成它。
    • 对不起,我没有得到答案 - 我赶上了其他事情。如果您在上面发布的内容满足您的需求,那么这才是真正重要的。不过,还有一些其他的事情需要考虑,是否在函数末尾有几个变量(final_tablef4)没有返回,所以可能不需要在那里?
    • @Sam Rogers:谢谢您的热情回复!你是对的 - 不需要“f4”。在这段代码的不同版本中,我也使用了 f4。在我发布的问题中,我决定不使用它。
    • 好的,我有时间就去试试。您能否添加有关该功能目标的更多详细信息?这只会让我更快地找出你的目标。例如。该函数将 作为输入(train_data 是否总是相同的随机值设置?x 是否只有 4 个值?等等),,并返回 。谢谢:)
    • 即我所追求的是对您试图解决的问题的全面描述,而不是您的函数产生的错误。这样我就可以尝试编写一个可以解决您的问题的函数,而不仅仅是编辑您编写的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-26
    • 2020-06-07
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-17
    相关资源
    最近更新 更多