R语言使用optim实现多参数外层双重优化时的传参报错问题
R双重优化中多参数外层函数调用optim()的传参报错解决方案
问题成因
optim()的传参逻辑是固定的:调用优化目标函数时,仅会把待优化的参数向量par作为第一个位置参数整体传入函数,不会自动将向量的各个元素拆分,匹配给目标函数的多个独立形参。
之前单参数的外层函数之所以能正常运行,是因为函数形参只有1个,和optim()/optimize()传入的单值参数刚好匹配,不存在参数拆分的问题。
当外层函数定义了两个独立形参first_factor和second_factor时,调用optim(par=c(0,2), outer_function_args)会把长度为2的par向量整体赋值给第一个形参first_factor,第二个形参second_factor没有接收到任何值,因此触发“参数缺失”的报错。
解决方法
有两种可落地的实现方案,都不需要改动内层优化的核心逻辑:
- 方案1:将外层待优化函数的入参调整为单个向量,在函数内部完成参数拆分
这是最贴合optim()传参习惯的写法,调整后的函数代码如下:
outer_function_args <- function(p) { # 从传入的待优化向量中拆分两个参数 first_factor <- p[1] second_factor <- p[2] inner_function <- constructor_function(c(first_factor, second_factor, 3, 4)) values <- optim(c(0, 0), inner_function)$par tot <- sum(values) return(tot) } # 验证原有函数的计算逻辑未被改动 outer_function_args(p = c(1, 2)) #> [1] -10 # 正常运行外层optim优化 optim(par = c(0, 2), fn = outer_function_args)
- 方案2:保留原有多参数函数定义,在
optim()调用时通过匿名函数做参数适配
适合不想修改已有函数结构的场景,用一层匿名函数承接optim()传入的向量参数,再拆分传递给原函数即可:
# 原有outer_function_args定义保持不变 outer_function_args <- function(first_factor, second_factor) { inner_function <- constructor_function(c(first_factor, second_factor, 3, 4)) values <- optim(c(0, 0), inner_function)$par tot <- sum(values) return(tot) } # 调用optim时增加匿名函数适配传参 optim( par = c(0, 2), fn = function(p) { outer_function_args(first_factor = p[1], second_factor = p[2]) } )
补充说明:如果外层优化需要给两个参数分别设置上下界,可以在函数内部拆分参数后,将对应的上下界向量按顺序传入
optim()的lower/upper参数即可,传参逻辑和单参数优化保持一致。当前示例中外层目标函数会随两个参数增大单调递减,如果没有设置边界,优化结果会随初始值漂移,属于目标函数本身的特性,和传参逻辑无关。
内容的提问来源于stack exchange,提问作者Emy
相关产品推荐
相关产品推荐

