最小化python函数,它在小间隔内是恒定的

时间:2018-03-27 11:15:43

标签: python numpy optimization scipy minimization

我想最小化带有边界和约束的区域上的凸函数,因此我尝试将scipy.optimize.minimizeSLSQP选项一起使用。但是我的功能只在离散点定义。线性插值似乎不是一个选项,因为在所有值中计算我的函数会占用太多时间。作为一个最小的工作示例我有:

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的电话可能需要一分钟。

1 个答案:

答案 0 :(得分:2)

如果您的功能不顺畅,基于梯度的优化技术将失败。当然,您可以使用不基于渐变的方法,但这些方法通常需要更多的功能评估。

以下两个选项可以发挥作用。

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])