我当前正在使用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)
我以正确的方式来处理吗?如何将列表或数组作为固定输入传递?
答案 0 :(得分:0)
以args
传递的元组将以*args
传递给目标函数。如果您以这种方式定义目标函数,则它期望单个输入参数(除speed
之外的其他参数被最小化),因此将单元素元组(p0,)
作为args
传递minimize
的关键字是完美的。您的错误发生在函数调用之后:
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个元素的数组)。这就是为什么您无法将形状(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中那样传递参数列表,则无需首先将那些变量分开,但是如果这四个输入在计算中涉及的方式非常不同,则处理每个变量可能很有意义分别从目标函数的定义开始。
答案 1 :(得分:0)
这些是线性约束,格式为Ax = b
。例如,
假设我们要固定前两个变量x0, x1
(您的a, b
):
A = [[ 1 0 0 ... ]
[ 0 1 0 ... ]]
b = [b0 b1]
有一种解决线性约束问题Ax = b
的一般方法
在此示例n - 2
中用较少的变量解决了不受约束的问题,
使用SVD。
my gists下的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.
"""
这可能对您的问题来说是矫kill过正。 但是,好问题- 环顾四周,试图通过5d了解粗糙的国家 仅改变一些您了解的变量, 是一件好事。