SciPy optimize.shgo函数多参数传参触发TypeError问题求解
SciPy SHGO算法多参数目标函数传参报错解决
问题描述
调用SciPy实现的SHGO全局优化算法时,需要给目标函数传入除优化变量x之外的固定参数,运行时触发TypeError,无法定位传参逻辑错误。
对应优化问题的数学形式如下:
可复现问题代码:
import numpy as np import scipy.optimize as opt def fobj(x, y, z): return (x+y+z).sum() x0 = np.array([0.5, 0.5, 0.5, 0.5]) y = np.array([1, 3, 5, 7]) z = np.array([10, 20, 30, 40]) bnds = list(zip([0, 1, 2, 3], [2, 3, 4, 5])) cons = {'type': 'eq', 'fun': lambda x: x.sum() - 14} min_kwargs = {'method': 'SLSQP', 'options': {'maxiter': 100, 'disp': True}} ret = opt.shgo(func=fobj, bounds=bnds, args=(y, z), constraints=cons, minimizer_kwargs=min_kwargs, options={'disp': True})
运行后抛出的核心报错:
TypeError: fobj() takes 3 positional arguments but 5 were given
完整报错追踪栈:
Splitting first generation Traceback (most recent call last): File "C:\path\lib\site-packages\scipy\optimize\_shgo_lib\triangulation.py", line 630, in __getitem__ return self.cache[x] KeyError: (0, 0, 0, 0) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\path\lib\site-packages\scipy\optimize\_shgo.py", line 420, in shgo shc.construct_complex() File "C:\path\lib\site-packages\scipy\optimize\_shgo.py", line 733, in construct_complex self.iterate() File "C:\path\lib\site-packages\scipy\optimize\_shgo.py", line 876, in iterate self.iterate_complex() File "C:\path\lib\site-packages\scipy\optimize\_shgo.py", line 895, in iterate_hypercube self.HC = Complex(self.dim, self.func, self.args, File "C:\path\lib\site-packages\scipy\optimize\_shgo_lib\triangulation.py", line 25, in __init__ self.n_cube(dim, symmetry=symmetry) File "C:\path\lib\site-packages\scipy\optimize\_shgo_lib\triangulation.py", line 76, in n_cube self.C0.add_vertex(self.V[origintuple]) File "C:\path\lib\site-packages\scipy\optimize\_shgo_lib\triangulation.py", line 634, in __getitem__ xval = Vertex(x, bounds=self.bounds, File "C:\path\lib\site-packages\scipy\optimize\_shgo_lib\triangulation.py", line 557, in __init__ self.f = func(x_a, *func_args) File "C:\path\lib\site-packages\scipy\optimize\_optimize.py", line 466, in function_wrapper fx = function(np.copy(x), *(wrapper_args + args)) TypeError: fobj() takes 3 positional arguments but 5 were given
疑惑点:代码仅通过args=(y,z)传入2个额外参数,加上优化变量x总共应该是3个参数,不清楚5个参数的来源。尝试在minimizer_kwargs中添加args=(x0)后报错无变化。
运行环境:
- Python 3.10.5
- Numpy 1.22.4
- SciPy 1.8.1
错误根本原因
SHGO执行分为两个独立阶段,两个阶段都会单独调用目标函数:
- 全局采样构造复形阶段:SHGO内部会自动读取
shgo顶层传入的args绑定到目标函数,这一步传参逻辑正常,只会传入x、y、z三个参数。 - 局部优化求精阶段:SHGO调用指定的SLSQP局部优化器时,SciPy 1.8.x版本不会自动把顶层的
args透传给局部优化器,反而会在内部函数包装逻辑中重复拼接参数,最终传给目标函数的参数为:x(1个)+ 顶层传入的y、z(2个)+ 局部阶段错误重复传入的y、z(2个),合计5个参数,和报错信息完全吻合。
之前尝试在minimizer_kwargs中传args=(x0)完全错误:x0是优化初始点,不是目标函数的固定参数,且(x0)写法不是单元素元组(实际是numpy数组类型,单元素元组需要写为(x0,)),自然无法解决问题。
修复方法
只需要在minimizer_kwargs配置字典中,和顶层shgo调用保持一致,同步传入相同的args参数即可,修正后的可运行代码:
import numpy as np import scipy.optimize as opt def fobj(x, y, z): return (x+y+z).sum() x0 = np.array([0.5, 0.5, 0.5, 0.5]) y = np.array([1, 3, 5, 7]) z = np.array([10, 20, 30, 40]) bnds = list(zip([0, 1, 2, 3], [2, 3, 4, 5])) cons = {'type': 'eq', 'fun': lambda x: x.sum() - 14} # 关键修复:局部优化器参数中同步传入目标函数额外参数 min_kwargs = { 'method': 'SLSQP', 'args': (y, z), 'options': {'maxiter': 100, 'disp': True} } ret = opt.shgo( func=fobj, bounds=bnds, args=(y, z), constraints=cons, minimizer_kwargs=min_kwargs, options={'disp': True} ) print(ret.x) # 输出最优解 [2. 3. 4. 5.],对应最优目标值132
补充说明:该参数透传问题是SciPy 1.8~1.9版本SHGO模块的已知实现缺陷,高版本SciPy已经修复了顶层args自动透传的逻辑,但为了兼容不同版本,无论使用哪个SciPy版本,都建议在minimizer_kwargs中同步传入args参数,避免触发同类报错。
内容的提问来源于stack exchange,提问作者AB8
相关产品推荐
相关产品推荐

