Python 使用scipy.optimize.minimize使用固定参数

Python 使用scipy.optimize.minimize使用固定参数,python,optimization,scipy,minimize,Python,Optimization,Scipy,Minimize,我目前正在使用scipy optimize.minimize来获得一个具有5个参数的函数的最小值。我希望四个输入作为函数的固定参数输入,我希望optimize.minimize给我第五个输入的值,以便从函数中获得尽可能低的输出 以下是我目前拥有的代码: from numpy import array import scipy.optimize as optimize from scipy.optimize import minimize def objective(speed, params)

我目前正在使用scipy optimize.minimize来获得一个具有5个参数的函数的最小值。我希望四个输入作为函数的固定参数输入,我希望optimize.minimize给我第五个输入的值,以便从函数中获得尽可能低的输出

以下是我目前拥有的代码:

from numpy import array
import scipy.optimize as optimize
from scipy.optimize import minimize

def objective(speed, params):
    a,b,c,d=params
    return abs(rg.predict([[speed,params]]))

p0=np.array([[98.3,46.9,119.9,59.1]])

x0=np.array([[4]])
result = optimize.minimize(objective, x0, args=(p0,),method='nelder-mead')
print(result.x)
我正在寻找一种能够在optimize.minimize函数中传递固定参数列表或数组的方法。但是,上面的代码给了我这个错误:

ValueError: not enough values to unpack (expected 4, got 1)
我似乎能让它工作的唯一方法是在输入中硬编码如下:

def objective(params):
 a=100
 b=20
 c=119.9
 d=params
 e=59.1
 return abs(rg.predict([[a,b,c,d,e]]))

x0=np.array([[4.5]])
result = optimize.minimize(objective, x0, method='nelder-mead')
print(result.x)

我是否以正确的方式处理这个问题?如何将列表或数组作为固定输入传入

作为
args
传递的元组将作为
*args
传递给目标函数。如果您按照您的方式定义目标函数,它需要一个输入参数(除了要最小化的
speed
),因此将单个元素元组
(p0,)
作为
args
关键字传递到
最小化
是完美的。您的错误出现在函数调用之后:

ValueError: not enough values to unpack (expected 4, got 1)
这实际上来自目标函数的第一行:

a,b,c,d=params # params = np.array([[98.3,46.9,119.9,59.1]])
作为
p0
传递的数组有两组方括号,因此它具有形状
(1,4)
。数组沿其第一维解压,因此在解压过程中,其行为类似于1元组(包含4元素数组)。这就是为什么不能将shape
(1,4)
解包为四个变量,从而导致错误

这基本上是一个打字错误(一对方括号太多),不值得完整回答。我之所以写这篇文章,是因为根据您的用例,直接在函数签名中定义这些参数可能更容易,并在最小化过程中相应地传递这些参数:

def objective(speed, a, b, c, d):
    ... # return stuff using a,b,c,d

# define a0, b0, c0, d0 as convenient
result = optimize.minimize(objective, x0, args=(a0,b0,c0,d0), method='nelder-mead')

这样定义函数是否更优雅取决于如何轻松定义固定参数,以及在
objective
中使用这些参数会发生什么。如果你只是想在你的MCVE中传递参数列表,那么首先就没有必要分离这些变量,但是,如果计算中涉及的这四个输入非常不同,那么从目标函数的定义开始分别处理每个输入可能是有意义的。

这些是线性约束,形式为
Ax=b
。例如 假设我们希望固定前两个变量
x0,x1
(您的
a,b
):

有一种通用的方法可以解决线性约束问题
Ax=b
对于变量较少的无约束问题,在本例中,
n-2
, 使用。
minlin.py
下 是此进程的numpy SVD的一页包装器。其文件:

""" Minlin: convert linear-constrained min f(x): Ax = b
to unconstrained min in fewer variables.
For example, 10 variables with 4 linear constraints, A 4 x 10,
-> 6 unconstrained variables:

minlin = Minlin( A, b, bigfunc, verbose=1 )   # bigfunc( 10 vars )
then
minimize( minlin.littlefunc, minlin.y0 ... )  # littlefunc( 6 vars )
    with your favorite unconstrained minimizer. For example,

from scipy.optimize import minimize
res = minimize( minlin.littlefunc, minlin.y0 ... )
fbest = res.fun
ybest = res.x  # 6 vars
xbest = minlin.tobig(ybest)  # 10 vars
    = minlin.x0  + y . nullspace  from svd(A)
    x0 = Ainv b = lstsq( A, b )

Methods: .func(x) .tonullspace(X) .torowspace(X) .tobig(y)
Attributes: .sing .Vt .Vtop .Vnull .x0

How it works, in a simple case:
consider holding x0 = b0, x1 = b1 fixed, i.e.
A = [[ 1 0 0 ... ]
     [ 0 1 0 ... ]]
We can minimize unconstrained over the n - 2 variables [x2 x3 ...]
if we could find them / find a basis for them, given just A.
This is what SVD / Minlin does.
"""
对于你的问题来说,这可能是矫枉过正。 但是,好问题-- 环顾四周,试图了解5d中的粗糙国家 只改变一些你能理解的变量,
这是一件好事。

谢谢!!当我将参数直接放入args时,它确实起作用。不过我还有一个问题。当我保持代码的其余部分不变并尝试删除额外的方括号时,我会遇到以下错误:ValueError:设置带有序列的数组元素。@DanaMcDowelle您可能需要更具体一些:您在哪里尝试删除方括号?当您尝试将非标量赋值给数组的元素时,通常会发生此错误,例如
arr=np.arange(3);arr[0]=[1,2]
。除了未定义的
rg.predict
调用之外,我在您的代码中没有看到类似的内容,我不知道该调用可能是什么:)
""" Minlin: convert linear-constrained min f(x): Ax = b
to unconstrained min in fewer variables.
For example, 10 variables with 4 linear constraints, A 4 x 10,
-> 6 unconstrained variables:

minlin = Minlin( A, b, bigfunc, verbose=1 )   # bigfunc( 10 vars )
then
minimize( minlin.littlefunc, minlin.y0 ... )  # littlefunc( 6 vars )
    with your favorite unconstrained minimizer. For example,

from scipy.optimize import minimize
res = minimize( minlin.littlefunc, minlin.y0 ... )
fbest = res.fun
ybest = res.x  # 6 vars
xbest = minlin.tobig(ybest)  # 10 vars
    = minlin.x0  + y . nullspace  from svd(A)
    x0 = Ainv b = lstsq( A, b )

Methods: .func(x) .tonullspace(X) .torowspace(X) .tobig(y)
Attributes: .sing .Vt .Vtop .Vnull .x0

How it works, in a simple case:
consider holding x0 = b0, x1 = b1 fixed, i.e.
A = [[ 1 0 0 ... ]
     [ 0 1 0 ... ]]
We can minimize unconstrained over the n - 2 variables [x2 x3 ...]
if we could find them / find a basis for them, given just A.
This is what SVD / Minlin does.
"""