Scipy.optimize SHGO的sobol采样触发TypeError问题求助
SHGO Sobol采样方法触发TypeError的原因与解决办法
问题根源
使用SciPy SHGO优化器的'sobol'采样方法时,约束函数会被额外传入目标函数的args参数(示例里的(0.3, 0.3)),但你定义的约束lambda只接受单个参数y,导致参数数量不匹配,触发TypeError: <lambda>() takes 1 positional argument but 3 were given。而'simplicial'采样方法和SLSQP在约束处理逻辑上不会传递这些额外参数,所以能正常运行。
快速修复方案
修改约束函数,让它接受任意数量的额外参数(哪怕用不到),用Python的可变参数语法*args即可:
cons = ({'type':'ineq', 'fun': lambda y, *args: y[0]-y[0]**2-y[1]**2})
修复后的完整代码
替换约束定义后的完整可运行代码:
import numpy as np from numpy import linalg as la import scipy as sc import scipy.optimize as opt print("numpy version: ", np.__version__) print("scipy version: ", sc.__version__) # d-dim Shannon entropy def ShEntr(x): s=0 for p_i in x: if p_i > 1e-16 and p_i < 1-1e-16: s = s - p_i*np.log2(p_i) return s # Function to be optimized def fun(y, k, g): p,c = y mat = [[p,c],[c,1-p]] return -ShEntr(la.eigvals(mat)) # 加负号是因为SciPy优化器默认做最小化 # Optimization parameters x0 = [0.5,0.2] # SLSQP的初始点 boun = [(0,1),(0,1)] # 参数边界 # 修复后的约束函数,支持接受额外参数 cons = ({'type':'ineq', 'fun': lambda y, *args: y[0]-y[0]**2-y[1]**2}) ## 执行优化 # SLSQP res = opt.minimize(fun, x0, (0.3,0.3), method='SLSQP', constraints=cons, bounds=boun, options={'maxiter':10000}) print("SLSQP: ", -res.fun) # SHGO: simplicial res = opt.shgo(fun, bounds=boun, args=(0.3,0.3), n = 30, iters = 5, sampling_method = 'simplicial', constraints=cons) print("SHGO simplicial: ", -res.fun) # SHGO: sobol res = opt.shgo(fun, bounds=boun, args=(0.3,0.3), n = 30, iters = 5, sampling_method = 'sobol', constraints=cons) print("SHGO sobol: ", -res.fun)
运行后三个优化任务都能正常完成,不会再出现参数不匹配的错误。
补充说明
这个问题是SciPy 1.7.3版本中SHGO模块'sobol'采样方法的逻辑bug——错误地将目标函数的args传递给了约束函数。如果你能升级到SciPy 1.10及以上版本,这个问题可能已经被官方修复,但修改约束函数的参数兼容性是更快捷的临时解决办法。
内容的提问来源于stack exchange,提问作者Sasche
相关产品推荐
相关产品推荐

