使用 scipy.optimize 动态选择要在 python 中最小化函数的参数
Dynamically choose argument for which to minimize a function in python using scipy.optimize
我有一个将变量列表作为参数的函数,我想使用 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 技巧?
非常感谢您的帮助!
如您所知,要最小化的函数会根据参数的不同而变化
给出。所以我们需要编写一些动态定义函数的代码。
一种方法是定义一个模板字符串,进行一些字符串格式化以
根据给定的参数修改模板,然后使用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
我只是想使用列表 arr
作为单个输入提供关于未知数量变量的 的改编,其中要拟合的参数设置为 None
。
最小化 fm
的函数是一个虚拟函数,只是尝试使用 numpy.std
.
来最小化数组的标准差
它看起来有点笨重而且不太符合 Python 风格,但它确实有效。
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+"))"
我有一个将变量列表作为参数的函数,我想使用 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 技巧?
非常感谢您的帮助!
如您所知,要最小化的函数会根据参数的不同而变化
给出。所以我们需要编写一些动态定义函数的代码。
一种方法是定义一个模板字符串,进行一些字符串格式化以
根据给定的参数修改模板,然后使用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
我只是想使用列表 arr
作为单个输入提供关于未知数量变量的 None
。
最小化 fm
的函数是一个虚拟函数,只是尝试使用 numpy.std
.
它看起来有点笨重而且不太符合 Python 风格,但它确实有效。
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+"))"