算法简介
DIRECT,即DIvinding RECTangle (矩形分割)算法。其基本思路是, 对于待优化函数 f ( x ) f(x) f(x),将求解区域分割为多个超立方体,并估计其中心的函数值 f ( x i ) f(x_i) f(xi)。其迭代过程,则把每个超立方体都视作一个新的求解区域,从而继续分割,直到满足求解条件。
函数封装
在scipy.optimize
中,提供的DIRECT算法如下
direct(func, bounds, *, args=(), eps=0.0001, maxfun=None, maxiter=1000, locally_biased=True, f_min=- inf, f_min_rtol=0.0001, vol_tol=1e-16, len_tol=1e-06, callback=None)
其中func为待优化函数,bounds为定义域区间,这两个参数为必填的参数,其他参数的含义如下:
- args 为参数元组,即func的输入参数除了待优化值之外,还可以包括args
- eps 最小误差,默认为 1 0 − 4 10^{-4} 10−4
- maxfun 目标函数的近似上界
- maxiter 最大迭代次数,默认1000
- locally_biased 为True时,使用DIRECT_L算法;否则使用无偏的DIRECT算法。
- f_min 全局最优值,当全局最优值为已知时可设,用于求解全局最优的参数。
- f_min_rtol 只有设置f_min后才可设置f_min_rtol,当优化结果和f_min之差小于f_min_rtol时停止优化。
- vol_tol 此为超立方体的最小体积,也是一个终止条件。
- len_tol 当locally_biased为True时,若超立方体的最小边小于len_tol时终止运行。若locally_biased为False,由于采用无偏的DIRECT算法,故而边长是相等的。
- callback 运行结束之后的回调函数。
测试
下面对direct
函数做一个简单的测试
import numpy as np
from scipy.optimize import direct
func = lambda x: np.cos(14.5 * x - 0.3) + (x + 0.2) * x
ret = direct(func, [[-2,2]], maxiter=200)
print(ret)
'''
fun: -1.000876183984045
message: 'Number of function evaluations done is larger than maxfun=1000'
nfev: 1003
nit: 75
status: 1
success: False
x: array([-0.19506963])
'''
其返回值是一个OptimizeResult
对象,其中fun
为优化结果,x是在此种优化结果时,其自变量的取值。
上面这个只是对单值函数进行了测试,属于牛刀小试,接下来搞一个变态一点的多元函数
其中func
为待优化函数,bounds
为求解区域,为必要的参数。
import numpy as np
def test(xs):
_sum = 0.0
for i in range(len(xs)):
_sum = _sum + np.cos((xs[i]*i)/5)*(i+1)
return _sum
bounds = [[-15,15] for _ in range(5)]
ret = direct(test, bounds)
msg = f"全局最小值" + ", ".join([f"{x:.4f}" for x in ret.x])
msg += f"\nf(x)={ret.fun:.4f}"
print(msg)
其优化结果为
全局最小值14.4856, -14.9931, 7.8601, 5.2401, -11.7833
f(x)=-12.9796