我有一个函数,它将变量列表作为参数,我想使用scipy.optimize.minimize来最小化这个函数。
问题是在运行时决定参数列表中的哪个变量应该进行最小化。所有其他变量都将获得固定值。
让我们举个例子来澄清:
a = 1
c = 1.1
d = -1.2
def func( b ):
return function_to_minimize( array=[a,b,c,d] )
sol = scipy.optimize.minimize( func, [b0], args=(a,c,d) )
但是,这可能是b
,c
和d
已知,我想优化a
以找到最小解决方案。
为了使它更复杂,列表的长度也是未知的。这意味着可能存在变量e
,f
,g
,......等等。
实际表示法如下。 None
元素是应该优化的元素。
array = [1, 1.1, None, -0.5, 4]
def func(arr):
return function_to_minimize(arr)
startvalue = 1.0
sol = scipy.optimize.minimize( func, [startvalue], args='Array without None' )
有没有办法告诉scipy.optimize.minimize要优化哪个元素?我可以做一个聪明的lambda技巧吗?
我真的很感谢你的帮助!
答案 0 :(得分:1)
如您所知,要最小化的功能会根据参数而变化
给出。所以我们需要编写一些动态定义函数的代码。
一种方法是定义模板字符串,进行一些字符串格式化
根据给定的参数修改模板,然后使用exec
定义功能。这有一些优先权 - 标准库使用此technique to define namedtuples。
因此,例如,如果我们希望最小化的表达式是
4*(b-a)**2 + 5*(c-d)**2
然后你可以使用
import textwrap
import scipy.optimize as optimize
def make_model(*fixed):
template = textwrap.dedent("""
def func(variable, {fixed}):
{variable} = variable
return 4*(b-a)**2 + 5*(c-d)**2
""")
variable = set(('a', 'b', 'c', 'd')).difference(fixed)
ns = dict()
funcstr = template.format(variable=', '.join(variable), fixed=', '.join(fixed))
print(funcstr) # comment out if you don't want to see the function
exec funcstr in ns
return ns['func']
def solve(initial_guess, **givens):
fixed = tuple(givens.keys())
vals = tuple(givens.values())
sol = optimize.minimize(make_model(*fixed), initial_guess, args=vals)
return sol
print(solve(initial_guess=1, a=1, c=1.1, d=-1.2))
产生
def func(variable, a, c, d):
b = variable
return 4*(b-a)**2 + 5*(c-d)**2
status: 0
success: True
njev: 1
nfev: 3
hess_inv: array([[1]])
fun: array([ 26.45])
x: array([ 1.])
message: 'Optimization terminated successfully.'
jac: array([ 0.])
nit: 0
print(solve(initial_guess=(1, 1), a=1, c=1.1))
产量
def func(variable, a, c):
b, d = variable
return 4*(b-a)**2 + 5*(c-d)**2
status: 0
success: True
njev: 3
nfev: 12
hess_inv: array([[1, 0],
[0, 1]])
fun: 2.4611848645596973e-16
x: array([ 0.99999999, 1.1 ])
message: 'Optimization terminated successfully.'
jac: array([ 1.19209279e-08, 2.88966118e-08])
nit: 1
答案 1 :(得分:0)
我只想使用列表arr
作为单个输入,提供有关未知数量变量的unutbu's answer的修改,其中要拟合的参数设置为None
。
最小化fm
的函数是一个虚函数,只是尝试使用numpy.std
最小化数组的标准偏差。
它看起来有点笨重而且不是非常pythonesque,但它的确有效。
import textwrap
import scipy.optimize as optimize
def make_model(n,*fixed):
template = textwrap.dedent("""
import numpy as np
def fm(arr):
return np.std(arr)
def func(variable, {fixed}):
{variable} = variable
return fm(["""+",".join(["a"+str(i) for i in range(n)])+"""])
""")
settuple = tuple(['a'+str(i) for i in range(n)])
variable = set(settuple).difference(fixed)
ns = dict()
funcstr = template.format(variable=', '.join(variable), fixed=', '.join(fixed))
print(funcstr) # comment out if you don't want to see the function
exec funcstr in ns
return ns['func']
def solve(initial_guess, n, **givens):
fixed = tuple(givens.keys())
vals = tuple(givens.values())
sol = optimize.minimize(make_model(n,*fixed), initial_guess, args=vals)
return sol
arr = [1, 1.1, None, -0.5, 4, 3]
s = ""
for i,a in enumerate(arr):
if a is not None:
s+=", a"+str(i)+"="+str(a)
print "print(solve(initial_guess=1, n="+str(len(arr))+s+"))" # comment out if you don't want to see the function
exec "print(solve(initial_guess=1, n="+str(len(arr))+s+"))"