最小化 python 函数,它在小间隔上是常数
Minimization python function which is constant on small intervals
我想在有边界和约束的区域上最小化凸函数,因此我尝试使用 scipy.optimize.minimize
和 SLSQP
选项。但是我的函数只在离散点定义。线性插值似乎不是一种选择,因为在所有值中计算我的函数会花费太多时间。作为一个最小的工作示例,我有:
from scipy.optimize import minimize
import numpy as np
f=lambda x : x**2
N=1000000
x_vals=np.sort(np.random.random(N))*2-1
y_vals=f(x_vals)
def f_disc(x, x_vals, y_vals):
return y_vals[np.where(x_vals<x)[-1][-1]]
print(minimize(f_disc, 0.5, method='SLSQP', bounds = [(-1,1)], args = (x_vals, y_vals)))
产生以下输出:
fun: 0.24999963136767756
jac: array([ 0.])
message: 'Optimization terminated successfully.'
nfev: 3
nit: 1
njev: 1
status: 0
success: True
x: array([ 0.5])
我们当然知道它是错误的,但是 f_disc
的定义让优化器相信它在给定索引处是常量。对于我的问题,我只有 f_disc
而无法访问 f
。此外,调用 f_disc
可能需要一分钟。
如果您的功能不流畅gradient-based优化技术将失败。当然你可以使用不基于梯度的方法,但这些通常需要更多的函数评估。
这里有两个可行的选项。
nelder-mead method不需要梯度,但它有一个缺点,就是不能处理边界或约束:
print(minimize(f_disc, 0.5, method='nelder-mead', args = (x_vals, y_vals)))
# final_simplex: (array([[ -4.44089210e-16], [ 9.76562500e-05]]), array([ 2.35756658e-12, 9.03710082e-09]))
# fun: 2.3575665763730149e-12
# message: 'Optimization terminated successfully.'
# nfev: 32
# nit: 16
# status: 0
# success: True
# x: array([ -4.44089210e-16])
differential_evolution
是一个优化器,不对平滑度做任何假设。它不仅可以处理边界;它需要他们。但是,它比 nelder-mead.
需要更多的函数评估
print(differential_evolution(f_disc, bounds = [(-1,1)], args = (x_vals, y_vals)))
# fun: 5.5515134011907119e-13
# message: 'Optimization terminated successfully.'
# nfev: 197
# nit: 12
# success: True
# x: array([ 2.76298719e-06])
我想在有边界和约束的区域上最小化凸函数,因此我尝试使用 scipy.optimize.minimize
和 SLSQP
选项。但是我的函数只在离散点定义。线性插值似乎不是一种选择,因为在所有值中计算我的函数会花费太多时间。作为一个最小的工作示例,我有:
from scipy.optimize import minimize
import numpy as np
f=lambda x : x**2
N=1000000
x_vals=np.sort(np.random.random(N))*2-1
y_vals=f(x_vals)
def f_disc(x, x_vals, y_vals):
return y_vals[np.where(x_vals<x)[-1][-1]]
print(minimize(f_disc, 0.5, method='SLSQP', bounds = [(-1,1)], args = (x_vals, y_vals)))
产生以下输出:
fun: 0.24999963136767756
jac: array([ 0.])
message: 'Optimization terminated successfully.'
nfev: 3
nit: 1
njev: 1
status: 0
success: True
x: array([ 0.5])
我们当然知道它是错误的,但是 f_disc
的定义让优化器相信它在给定索引处是常量。对于我的问题,我只有 f_disc
而无法访问 f
。此外,调用 f_disc
可能需要一分钟。
如果您的功能不流畅gradient-based优化技术将失败。当然你可以使用不基于梯度的方法,但这些通常需要更多的函数评估。
这里有两个可行的选项。
nelder-mead method不需要梯度,但它有一个缺点,就是不能处理边界或约束:
print(minimize(f_disc, 0.5, method='nelder-mead', args = (x_vals, y_vals)))
# final_simplex: (array([[ -4.44089210e-16], [ 9.76562500e-05]]), array([ 2.35756658e-12, 9.03710082e-09]))
# fun: 2.3575665763730149e-12
# message: 'Optimization terminated successfully.'
# nfev: 32
# nit: 16
# status: 0
# success: True
# x: array([ -4.44089210e-16])
differential_evolution
是一个优化器,不对平滑度做任何假设。它不仅可以处理边界;它需要他们。但是,它比 nelder-mead.
print(differential_evolution(f_disc, bounds = [(-1,1)], args = (x_vals, y_vals)))
# fun: 5.5515134011907119e-13
# message: 'Optimization terminated successfully.'
# nfev: 197
# nit: 12
# success: True
# x: array([ 2.76298719e-06])