SciPy:传递参数以优化.shgo函数时出现问题

i2loujxw  于 2022-11-10  发布在  Go
关注(0)|答案(2)|浏览(257)

我尝试使用SciPy中实现的SHGO算法,但是当目标函数使用多个参数时,我遇到了问题。如果我正确理解了错误,我没有将额外的参数传递给目标函数,但是我看不出语法哪里有错。有人能解释一下错误的根本原因是什么以及如何修复吗?
下面是我所面临的问题的一个可重复的例子。

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})

运行时,将显示以下追溯。

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

我不明白为什么会引发TypeError。它是说传递给目标函数fobj的参数是5个而不是3个,但据我所知,我只传递了(y, z),所以我看不出它们怎么会是5个!
请注意,我也尝试过将局部极小化字典重写为min_kwargs = {'method': 'SLSQP', 'args': (x0), 'options': {'maxiter': 100, 'disp': True}},但我一直面临着同样的错误。我确信我传递的参数不正确,但我不知道如何正确地做。任何帮助将不胜感激。
我使用的是:Python 3.10.5、Numpy 1.22.4和SciPy 1.8.1。

ff29svar

ff29svar1#

正如您所发现的,问题是bug in shgo
你可以通过避免使用args参数来避免shgo中的bug。不要使用args,而是使用一个fobj的 Package 器来捕获闭包中的yz。一个简单的方法是使用lambda表达式:将shgo的第一个参数从func=fobj更改为func=lambda x, y=y, z=z: fobj(x, y, z),并从调用中删除args参数。

kr98yfug

kr98yfug2#

问题是sum是一个方法,而不是数组的属性。
如果你把目标函数

def fobj(x, y, z):
    return (x+y+z).sum()

此外,在开发版本上有一个bug(很快就会更新)。
该方法似乎也不是很健壮,对于sum(x)= 14,它只有一个解,这可能是一个问题,因为有效的搜索空间是0维的,但即使我将其放宽到sum(x)= 12这样的情况,该方法也不能给予解。
下面是一个更完整的工作示例

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], [3,4,5,6]))
cons = {'type': 'eq', 'fun': lambda x: x.sum() - 9}
min_kwargs = {'method': 'SLSQP', 'options': {'maxiter': 10000, 'disp': True}}
ret = opt.shgo(func=lambda x: fobj(x, y, z), bounds=bnds, args=(), constraints=cons, 
               minimizer_kwargs=min_kwargs, options={'disp': True})

相关问题