【问题标题】:R : Function is returning Unused ArgumentsR:函数返回未使用的参数
【发布时间】:2021-09-18 11:14:30
【问题描述】:

我正在使用 R。我正在学习优化并尝试遵循以下参考资料中的说明:https://www.rdocumentation.org/packages/pso/versions/1.0.3/topics/psoptimhttps://rpubs.com/Argaadya/intro-PSO

对于这个例子,我首先生成一些随机数据:

#load libraries
library(dplyr)


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

从这里,我定义了我想要优化的功能(“适应度”)。此函数接受 7 个输入并计算“总”平均值(单个标量值)。此功能所需的输入是:

  • “random_1”(80 到 120 之间)
  • “random_2”(介于“random_1”和 120 之间)
  • “random_3”(介于 85 和 120 之间)
  • “random_4”(介于 random_2 和 120 之间)
  • “split_1”(介于 0 和 1 之间)
  • “split_2”(介于 0 和 1 之间)
  • split_3"(介于 0 和 1 之间)

要优化的函数(“fitness”)定义如下(取这 7 个数字并返回单个标量“total” - 目标是获得这 7 个数字的“total”的最大值):

fitness <- function(random_1, random_2, random_3, random_4, split_1, split_2, split_3) {

    #bin data according to random criteria
    train_data <- train_data %>% mutate(cat = ifelse(a1 <= random_1 & b1 <= random_3, "a", ifelse(a1 <= random_2 & b1 <= random_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)
    
    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 = quantile(c1, prob = split_1)))
    
    table_b = data.frame(b_table%>% group_by(cat) %>%
                             mutate(quant = quantile(c1, prob = split_2)))
    
    table_c = data.frame(c_table%>% group_by(cat) %>%
                             mutate(quant = quantile(c1, prob = split_3)))
    
    
    
    
    #create a new variable ("diff") that measures if the quantile is bigger than the value of "c1"
    table_a$diff = ifelse(table_a$quant > table_a$c1,1,0)
    table_b$diff = ifelse(table_b$quant > table_b$c1,1,0)
    table_c$diff = ifelse(table_c$quant > table_c$c1,1,0)
    
    #group all tables
    
    final_table = rbind(table_a, table_b, table_c)
# calculate the total mean : this is what needs to be optimized
    mean = mean(final_table$diff)
    
    
}

从这里开始,我有兴趣使用“ps_optim”函数来优化我刚刚定义的函数:

library(psoptim)
set.seed(90)
psoptim(rep(NA,3), fn = fitness, lower = c(80, random_1, 85, random_2, 0,0,0), upper = c(120,120,120,120,1,1,1))

但这会返回以下错误,提示存在一些“未使用的参数”:

Error in psoptim(rep(NA, 3), fn = fitness, lower = c(80, random_1, 85,  : 
  unused arguments (fn = fitness, lower = c(80, random_1, 85, random_2, 0, 0, 0), upper = c(120, 120, 120, 120, 1, 1, 1))

有人可以告诉我为什么会产生这个错误吗? 谢谢

【问题讨论】:

  • 确保使用?psoptim 调出该功能的帮助页面。这些根本不是正确的参数名称。 names(formals(psoptim)) 调出诸如“FUN”、“n”、“max.loop”之类的值......您似乎使用的是 pso::psoptim 而不是 psoptim::psoptim 的语法。确保您正在查看正确包装的文档。 library(psoptim) 加载与 library(pso) 不同的包
  • @MrFlick:感谢您的回复 - 我将查看文档。我是在 R 中编写和操作函数的新手,我仍在努力正确定义函数。例如,我不确定我是否正确定义了“健身”功能。如果你有时间,你能不能也看看这个问题:stackoverflow.com/questions/68280857/r-x-probs-outside-0-1

标签: r function loops optimization dplyr


【解决方案1】:

正如 cmets 中所指出的,如果你命名参数,你需要根据函数定义来命名它们。此外,上下界不是表达式,而必须是常量(即数字,而不是诸如 random_1 之类的名称)。

可以通过惩罚来处理此类约束:在目标函数中,计算变量是否超出其范围;如果是,则从目标函数中减去一个惩罚(如果你最大化)或添加一个惩罚(如果你最小化)。

有一些优化方法可以在创建新解决方案时直接处理此类约束。一种这样的方法是本地搜索。这是一个(粗略的)示例,我假设您希望最大化。我使用包NMOF(我维护)中的实现。该算法期望最小化,但这没问题:只需将目标函数值乘以 -1。 (请注意,许多优化算法都需要最小化模型。)

本地搜索的关键要素是邻域功能。它将给定的解决方案作为输入,并产生一个稍微改变的解决方案(邻居解决方案)。然后,Local Search 在可能的解决方案空间中随机游走(步骤在邻域函数中定义),接受更好的解决方案,但拒绝导致更差目标函数值的解决方案。

library("NMOF")
nb <- function(x, ...) {
    ## randomly pick one element in x and a small change
    i <- sample.int(length(x), 1)
    stepsize <- c(1, 1, 1, 1, 0.5, 0.5, 0.5)
    x[i] <- x[i] + runif(n = 1,
                         min = -stepsize[i],
                         max =  stepsize[i])

    ## 'repair' the solution
    x <- pmin(x, c(120,  120, 120,  120, 1, 1, 1))
    x <- pmax(x, c( 80, x[1],  85, x[2], 0, 0, 0))

    x
}

初步解决方案:

x0 <- c(100, 100, 100, 100, 0.5, 0.5, 0.5)
## [1] 100.0 100.0 100.0 100.0   0.5   0.5   0.5

随机步骤:

nb(x0)
## [1] 100.000 100.000 100.000 100.000   0.759   0.500   0.500

运行算法:

sol <- LSopt(function(x) -do.call(fitness, as.list(x)),
             list(neighbour = nb,
                  x0 = x0,
                  nI = 500))
-sol$OFvalue
## 0.998
sol$xbest
## [1] 112.329 112.331 111.777 112.331   1.000   0.771   1.000

如果您可以接受这样的方法,也许这个tutorial on heuristics 很有用。


这将是一个使用 PSO 的解决方案,使用 NMOF::PSopt

sol <- PSopt(function(x) -do.call(fitness, as.list(x)),
             list(nG = 25,  ## number of generations
                  nP = 20,  ## population size
                  repair = function(x) {
                     x <- pmin(x, c(120,  120, 120,  120, 1, 1, 1))
                     x <- pmax(x, c( 80, x[1],  85, x[2], 0, 0, 0))
                     x
                  },
                  min = c( 80, 80,  85, 85, 0, 0, 0),
                  max = c(120,  120, 120,  120, 1, 1, 1)))

-sol$OFvalue
## 0.998
sol$xbest
## [1]  98.551  98.551 110.750 108.639   1.000   0.312   1.000

【讨论】:

  • 非常感谢您的回答!我从来不知道这个包(NMOF)的存在!它看起来很酷,迫不及待地想了解更多。现在,我正在阅读这个 NMOF 包中的“粒子群优化”功能:rdrr.io/cran/NMOF/man/PSopt.html
  • 如果你有时间,你能告诉我如何正确使用你的包中的“PSopt”功能作为我的例子吗?如何使用“PSopt”来优化我与“train_data”一起定义的“fitness”函数?我正在查看示例并看到一般形式: sol
  • 我已经添加到答案中了。
  • 感谢您的回答!只是一个问题 - PSopt 可以接受“约束”,还是这些需要在优化函数(例如“适应度”)本身内编码? PSopt 是否可以同时对多个目标函数进行优化(例如,像这样 stackoverflow.com/questions/56359838/… )?非常感谢您的帮助!
  • @stats555:支持绑定约束;参见选项minmaxminmaxConstr,通过algo 传递。其他约束可以通过函数pen(惩罚)、repair(正如我在示例中所做的那样)和changeV 添加,也可以通过algo 传递。不支持开箱即用的多个目标(尽管集成它们并不太难)。
猜你喜欢
  • 2020-03-14
  • 2015-10-01
  • 1970-01-01
  • 2019-11-06
  • 1970-01-01
  • 2019-11-27
  • 2022-07-22
  • 1970-01-01
相关资源
最近更新 更多