我一直在尝试用SciPy optimizer SHGO进行一些全局优化,但在采样方法'sobol'
上遇到了问题。具体来说,我得到一个类型的错误:TypeError: <lambda>() takes 1 positional argument but 3 were given
。
让我怀疑它可能与采样方法本身的错误有关的事情是,当我使用simplicial
作为采样方法或不同的(仍然受约束的)优化算法(如SLSQP
)时,错误不会发生。
下面是代码,我有兴趣了解其他人是否可以重现此错误。
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)) #- sign in front of it due to the fact that scipy.otimize is a minimization
# Optimization parameters
x0 = [0.5,0.2] # Starting point for SLSQP
boun = [(0,1),(0,1)] # Optimization parameters bounds
cons = ({'type':'ineq', 'fun': lambda y: y[0]-y[0]**2-y[1]**2}) # Optimization parameters constraints
## Optimization
# 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)
我得到的结果是
numpy version: 1.20.3
scipy version: 1.7.3
SLSQP: 0.9999999999999942
SHGO simplicial: 1.0
Traceback (most recent call last):
File "... path /test.py", line 36, in <module>
res = opt.shgo(fun, bounds=boun, args=(0.3,0.3), n = 30, iters = 5, sampling_method = 'sobol', constraints=cons)
File "... path \Anaconda3\lib\site-packages\scipy\optimize\_shgo.py", line 419, in shgo
shc.construct_complex()
File "... path \Anaconda3\lib\site-packages\scipy\optimize\_shgo.py", line 733, in construct_complex
self.iterate()
File "... path \Anaconda3\lib\site-packages\scipy\optimize\_shgo.py", line 876, in iterate
self.iterate_complex()
File "... path \Anaconda3\lib\site-packages\scipy\optimize\_shgo.py", line 912, in iterate_delaunay
self.sampled_surface(infty_cons_sampl=self.infty_cons_sampl)
File "... path \Anaconda3\lib\site-packages\scipy\optimize\_shgo.py", line 1243, in sampled_surface
self.fun_ref()
File "... path \Anaconda3\lib\site-packages\scipy\optimize\_shgo.py", line 1356, in fun_ref
if g(self.C[i, :], *self.args) < 0.0:
TypeError: <lambda>() takes 1 positional argument but 3 were given
P.S.:我知道这里的函数fun(y, k, g)
不需要args k
和g
,但我只是(过度)简化了我使用的原始函数(需要k
和g
)来重现错误。
2条答案
按热度按时间von4xj4u1#
g(self.C[i, :], *self.args)
是scipy
如何将搜索变量和args
元组传递给您的函数。我认为你的fun(y,k,g)
处理得很好。但我认为错误在于调用了其中一个约束或边界函数。它们都必须具有相同的签名-2项
args
意味着3个变量。if g(self.C[i, :], *self.args) < 0.0:
测试某些函数结果与0.0的对比。2q5ifsrm2#
为了完整起见,我将解决方法报告为here
而不是给
opt.shgo
提供fun
和args=(k,g)
,只需定义一个新的lambda函数并将其提供给shgo
: