我有一个优化问题需要在 python 中解决。总体结构为
def foo(a, b, c, d, e):
# do something and return one value
def bar(a, b, c, d, e, f, g, h, i, j):
# do something and return one value
def func():
return foo(a, b, c, d, e) - bar(a, b, c, d, e, f, g, h, i, j)
我想使用 least_squares
最小化并返回 f、g、h、i 和 j
的值作为列表,其中平方差是 foo
和 bar
。我不确定如何为此使用 least_squares
。
我已经试过了:
# Initial values f, g, h, i, j
x0 =[0.5,0.5,0.5,0.05,0.5]
# Constraints
lb = [0,0,0,0,-0.9]
ub = [1, 100, 1, 0.5, 0.9]
x = least_squares(func, x0, lb, ub)
如何让 x
成为 f, g, h, i and j
最小值列表的返回值?
最佳答案
您当前定义问题的方式等同于最大化 bar
(假设您将 func
传递给最小化函数)。由于您没有将参数 a
更改为 e
,因此 func
基本上是常量与 bar< 的结果之间的差异
可以调整;由于负号,它将被尝试最大化,因为这将最小化整个函数。
我认为您真正想要最小化的是两个函数之间的绝对值或平方差。我用一个简单的例子来说明,我假设函数只返回参数的总和:
from scipy.optimize import minimize
def foo(a, b, c, d, e):
# do something and return one value
return a + b + c + d + e
def bar(a, b, c, d, e, f, g, h, i, j):
# do something and return one value
return a + b + c + d + e + f + g + h + i + j
def func1(x):
# your definition, the total difference
return foo(x[0], x[1], x[2], x[3], x[4]) - bar(x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9])
def func2(x):
# quadratic difference
return (foo(x[0], x[1], x[2], x[3], x[4]) - bar(x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]))**2
# Initial values for all variables
x0 = (0, 0, 0, 0, 0, 0.5, 0.5, 0.5, 0.05, 0.5)
# Constraints
# lb = [0,0,0,0,-0.9]
# ub = [1, 100, 1, 0.5, 0.9]
# for illustration, a, b, c, d, e are fixed to 0; that should of course be changed
bnds = ((0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0., 1), (0., 100.), (0, 1), (0, 0.5), (-0.9, 0.9))
res1 = minimize(func1, x0, method='SLSQP', bounds=bnds)
res2 = minimize(func2, x0, method='SLSQP', bounds=bnds)
然后你得到:
print res1.x
array([ 0. , 0. , 0. , 0. , 0. , 1. , 100. , 1. ,
0.5, 0.9])
和
print res1.fun
-103.4
如上所述,所有参数都将达到上限以最大化 bar
,从而最小化 func
。
对于适配函数 func2
,您会收到:
res2.fun
5.7408853312979541e-19 # which is basically 0
res2.x
array([ 0. , 0. , 0. , 0. , 0. ,
0.15254237, 0.15254237, 0.15254237, 0.01525424, -0.47288136])
因此,正如预期的那样,对于这种简单的情况,可以通过使这两个函数之间的差异变为 0 的方式来选择参数。显然,您的参数的结果不是唯一的,它们也可以全为 0。
我希望这有助于使您的实际功能发挥作用。
编辑:
正如您要求的 least_square
一样,它也可以正常工作(使用上面的函数定义);那么总差就可以了:
from scipy.optimize import least_squares
lb = [0,0,0,0,0,0,0,0,0,-0.9]
ub = [0.1,0.1,0.1,0.1,0.1,1, 100, 1, 0.5, 0.9]
res_lsq = least_squares(func1, x0, bounds=(lb, ub))
然后你会收到与上面相同的结果:
res_lsq.x
array([ 1.00000000e-10, 1.00000000e-10, 1.00000000e-10,
1.00000000e-10, 1.00000000e-10, 1.52542373e-01,
1.52542373e-01, 1.52542373e-01, 1.52542373e-02,
-4.72881356e-01])
res_lsq.fun
array([ -6.88463034e-11]) # basically 0
由于在这个问题中不会改变 5 个参数,我会将它们固定为某个值并且不会将它们传递给优化调用。
关于多变量的 Python 最小二乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42894618/