You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MLR3MBO中待优化目标函数能否包含非优化输入?

问题

在MLR3MBO中定义待优化的目标函数时,是否允许该函数包含无需优化的输入?

详细场景

数据来自人类参与计算机任务的过程,包含一系列y值(参与者按下的按钮)与对应的x值(屏幕显示内容)。我构建了一个人类认知模型(决策模型),用于描述给定参数p时,y如何由x生成。我需要优化参数p,即找到适配每个参与者的最优参数,每个参与者的x、y、p均不同。

我尝试通过以下方式定义待优化函数的输入列表:

xs=list(x1=x1,x2=x2... ,p1=p1,p2=p2)
domain=paradox::ps(p1=p_dbl(lower = -10, upper = 10),....)

即未将x1、x2等变量纳入domain定义,但运行以下代码时,程序无法识别x1、x2:

codomain=ps(y=p_dbl(tags='minimize'))
objective= ObjectiveRFun$new(
  fun=myModel,
  domain=domain,
  codomain=codomain)
instance = OptimInstanceSingleCrit$new(
  objective=objective,
  search_space=domain,
  terminator=trm('evals',n_evals =60)) # maybe change this?
# Gaussian Process, EI, DIRECT
surrogate = srlrn(lrn("regr.km",
                      covtype = "matern3_2",
                      optim.method = "gen",
                      nugget.stability = 10^-8, control = list(trace = FALSE)))
acq_function = acqf("ei")
acq_optimizer = acqo(opt("nloptr", algorithm = "NLOPT_GN_DIRECT_L"),
                     terminator = trm("stagnation", threshold = 1e-8))
optimizer = opt("mbo",
                loop_function = bayesopt_ego,
                surrogate = surrogate,
                acq_function = acq_function,
                acq_optimizer = acq_optimizer)

set.seed(2906)
start.time=Sys.time()
optimizer$optimize(instance)

最初选择MLR3MBO的原因是该函数在每次优化循环中计算耗时较长(包含多步骤for循环)。

解决方案

MLR3MBO允许目标函数包含无需优化的输入,但不能直接将非优化参数放进输入列表——ObjectiveRFun只会把domain里定义的参数传给目标函数。正确做法是通过闭包或参数绑定的方式,将x、y这类固定数据注入目标函数。

方法1:用闭包封装目标函数

把固定的x、y数据封装到外层函数中,返回仅接受优化参数p的目标函数,让目标函数能直接访问外部的固定数据:

# 封装固定参数,生成目标函数
create_objective_fun <- function(x_data, y_true) {
  function(p) {
    # 调用你的认知模型,用p和固定的x_data生成预测
    predictions <- myModel(p, x_data)
    # 计算需要最小化的损失(示例为MSE)
    loss <- mean((predictions - y_true)^2)
    return(list(y = loss))
  }
}

# 针对当前参与者的x、y数据创建专属目标函数
my_objective_fun <- create_objective_fun(x1, x2, y)

# 仅定义需要优化的参数p的domain
domain <- paradox::ps(
  p1 = p_dbl(lower = -10, upper = 10),
  p2 = p_dbl(lower = -5, upper = 5)
  # 添加其他需要优化的参数
)

# 初始化目标和实例
codomain <- ps(y = p_dbl(tags = 'minimize'))
objective <- ObjectiveRFun$new(
  fun = my_objective_fun,
  domain = domain,
  codomain = codomain
)

instance <- OptimInstanceSingleCrit$new(
  objective = objective,
  search_space = domain,
  terminator = trm('evals', n_evals = 60)
)

# 后续优化代码保持不变
surrogate <- srlrn(lrn("regr.km",
                      covtype = "matern3_2",
                      optim.method = "gen",
                      nugget.stability = 10^-8, control = list(trace = FALSE)))
acq_function <- acqf("ei")
acq_optimizer <- acqo(opt("nloptr", algorithm = "NLOPT_GN_DIRECT_L"),
                     terminator = trm("stagnation", threshold = 1e-8))
optimizer <- opt("mbo",
                loop_function = bayesopt_ego,
                surrogate = surrogate,
                acq_function = acq_function,
                acq_optimizer = acq_optimizer)

set.seed(2906)
start.time <- Sys.time()
result <- optimizer$optimize(instance)

方法2:用参数绑定简化函数

如果不想用闭包,可借助purrr::partial或mlr3misc::partial把固定参数绑定到目标函数上,生成仅接受p的新函数:

library(purrr)

# 改造myModel,让第一个参数为优化参数p,后续为固定的x、y
myModel <- function(p, x_data, y_true) {
  predictions <- # 你的模型计算逻辑,用p和x_data生成预测
  loss <- mean((predictions - y_true)^2)
  return(list(y = loss))
}

# 绑定固定参数x、y,生成只接受p的函数
bound_fun <- partial(myModel, x_data = x1, y_true = y)

# 后续domain、objective定义与方法1一致
domain <- paradox::ps(p1 = p_dbl(lower = -10, upper = 10), ...)
codomain <- ps(y = p_dbl(tags = 'minimize'))
objective <- ObjectiveRFun$new(fun = bound_fun, domain = domain, codomain = codomain)

关键说明

  • MLR3MBO的优化逻辑只会遍历domain内定义的参数,因此目标函数必须仅接受这些优化参数作为输入,非优化参数需通过外部环境传递。
  • 闭包是最常用的方式,能清晰隔离不同参与者的数据,你可以为每个参与者单独创建闭包函数,再分别执行优化。

内容的提问来源于stack exchange,提问作者JacquieS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 02:34:55