一维搜索

求解一元函数的最值过程称为一维搜索,不失一般性,本篇研究求函数最小值。由于一元线性函数可以通过单纯形法获得最小值,且单纯形算法非常稳定,所以在实践中如果需要使用一维搜索,这个一元函数通常是一个曲线函数,至少可以求二阶导数。一维搜索典型的例子是步长的确定,之前介绍的梯度求解函数最小值时,在获得函数在可行点的梯度后,需要将梯度向量取反然后乘以一个步长,这个步长不能太小,太小对于算法收敛速度太慢;当然也不能太长,太长会造成在极值点附近时穿越最值点,导致算法在极值点附近震荡。为了求一个合理的步长系数,通常可行点沿着某一个方向乘以一个步长系数,延伸得到新的可行点,将新的可行点带入目标函数求最小值,此时目标函数除了步长之外都是常量,目标函数变为一个一元函数,求解这个一元函数最小值就可以得到最优的步长系数。

    一维搜索根据目标函数的不同,选择策略也灵活多变,按算法特性大致可以分为两类,一类称为试探法,这种算法特征是利用最小值是一个‘谷底’,试探着用一个不断缩小的范围最后锁定谷底得到最小值;另一类算法叫做函数逼近法,函数逼近法用一个函数像尺子一样逼近目标函数其中一部分,通过尺子函数得到这部分的最小值后,同时得到目标函数下一个需要求最小值的片段,周而复始不断迭代后,新生成的尺子函数会越来越逼近目标函数最低点,最后当误差在一定范围内时,直接求解尺子函数的最小值即为目标函数的最小值。

    在介绍一维搜索算法之前先来介绍下凸函数的概念,介绍单纯形法时曾详细介绍过凸集,凸函数的定义与凸集相似,具体定义为, f(x)是定义在 凸集S上函数,如果凸集S上任意的x,y都有:

凸函数定义.gif

则称f(x)为凸函数,从图像上来看凸函数像一个碗,这个函数只有一个谷底,有时候也称这样的函数叫单峰函数:

凸函数图像.png

使用一维搜索时我们希望目标函数在定义域内是一个凸函数,或者在某一个区间内是一个凸函数,这样得到最小值是唯一的,当目标函数有多个谷底时,比如下面这个函数,一维搜索只能得到一个局部最小值。

局部最小值.jpg

一、试探算法:0.618法

    设一个在[a1,b1]上的凸函数f(x),并设误差系数e和缩短比例系数α(0<α<1),在初始区间[a1,b1]内取一个对称的子区间[λ1,μ1],对称含义是指λ1到端点a1的距离等于μ1到端点b1的距离,为满足对称性可以这样构建λ1、μ1:设λ1到端点b1的距离是区间[a1,b1]长度的α倍,μ1到端点a1的距离也是区间[a1,b1]长度的α倍,效果如下图所示:

试探法图示.png

得到λ1、μ1位置后将λ1、μ1带入目标函数后,会有以下两种情况:

情形一:f(λ1)<=f(μ1),这时将区间原端点b1设为μ1,a1依然保持不变,这时得到新的区间[a2,b2]=[a1,μ1],根据构建λ1,μ1时设定可以知道,此时新区间的长度缩短为原区间[a1,b1]长度的α。检查新区建长度μ1-a1,如果长度小于e则退出计算,这时最小值为(μ1+a1)/2;如果大于误差系数e,则在新的区间[a1,μ1]再次取一个对称子区间[λ2,μ2],λ2、μ2选择的规则与初始时一样,即λ2到b2的距离是区间[a2,b2]长度的α倍,μ2到端点a2的距离是区间[a2,b2]长度的α倍。

情形二:f(λ1)>f(μ1),这时将区间原端点a1设为λ1,b1保持不变,这时得到新的区间[a2,b2]=[λ1,b1],检查新区建长度b-λ1,如果长度小于e则退出计算,此时有最小值(λ1+b1)/2;如果大于误差系数e,则在新的区间[λ1,b1]再次取一个对称子区间[λ2,μ2],[λ2,μ2]区间设置规则与情形一相同。

    以上两种情形当新的子区间[ak,bk]距离大于误差e时,说明还没到达最小值点,这时需要将新生成子区间进一步切分得到区间[λk,μk],并将λk、μk再次带入目标函数计算,随后根据以上两种情形进行判断,直到距离小于误差e时退出计算。由于每次生成的子区间[ak,bk]是不断缩小的(0<α<1),算法最终能保证收敛于函数最小值点。另一方面,在算法实现中每次都是选择函数值较大一方缩短距离,就好比一个物体的重心偏向函数值较大一方,选择函数值较大一方缩短就能保证重心逐渐向最小值点靠近,或者说这样能保证函数最小值点始终在新生成区间中间的某个位置,从图像上来看,新的区间范围一直能覆盖函数谷底部分。如果要证明算法收敛性,可以将每次生成的区间理解为一个套区间,这个不断缩小的套区间最后极限是一个点,即最小值点。

    每次缩短的比例α为0.618时称为0.618法,我们知道0.618是一个黄金比例,α设为0.618时有什么特殊功效吗?假设在第k次迭代计算时得到新的区间[ak,bk],随后生成一个内部子区间[λk,μk],根据子区间对称性、缩短的比例α可以得到以下两个等式:

bk-λk=μk-ak

bk+1-ak+1=α(bk-ak)                                    ⑴

这样可以得到λk、μk的表达式:

λk=ak+(1-α)(bk-ak)

μk=ak+α(bk-ak)                                          ⑵

1)此时如果有f(λk)<=f(μk),根据算法特性可以知道下一次新区建间为:

[ak+1,bk+1]=[ak,μk]

同时需要在[ak+1,bk+1]内要得到检查点[λk+1,μk+1],从方程组⑵知道:

μk+1=ak+1+α(bk+1-ak+1)  =ak+α(μk-ak ) =ak+α^2(bk-ak ) 

此时如果有

ak+α^2(bk-ak ) =ak+(1-α)(bk-ak)          ⑶

μk+1=λk时,则代表新的μk+1不需要计算,只要上一轮的λk即可,而要满足方程 ⑶则是要满足一元二次方程:

α^2=1-α

由于要求α>0,解上面这个方程可以得出α=0.618

2)当f(λk)>f(μk),同样可以得到这样结论,当α=0.618时,λk+1不需要计算,只要取上一轮的μk即可。

由此可见,如果选择α=0.618,在每轮迭代获得检查点λ、μ时,其中一个参数一定可以取自上轮的参数,这样一来可以节省很多计算。将上述算法编制程序如下,这是利用0.618试探法求函数f(x)=2x2-3x-1最小值的python代码:

import numpy as np
#试探法求解f(x)=2x^2-3x-1最小值
def explore618():
    r=np.array([[-2,2]],dtype=np.float)
    alpha=0.618
    l=1e-5
    a,b,iterNum=r[0,0],r[0,1],0
    #shrinkDirection=1代表右端缩减,shrinkDirection=0代表左端缩减
    shrinkDirection=None
    while b-a >l:
        if shrinkDirection==None:
            lambda_k = a + (1 - alpha) * (b - a)
            mu_k = a + alpha * (b - a)
        if shrinkDirection==1:
            mu_k=lambda_k
            lambda_k = a + (1 - alpha) * (b - a)
        if shrinkDirection==0:
            lambda_k=mu_k
            mu_k = a + alpha * (b - a)
        if(2*lambda_k**2-3*lambda_k-1)<=(2*mu_k**2-3*mu_k-1):
            a,b,shrinkDirection=a,mu_k,1
        else:
            a, b ,shrinkDirection= lambda_k, b,0
            pass
        iterNum = iterNum + 1
    x=(b+a )/2
    return x,2*x**2-3*x-1,iterNum




if __name__ == '__main__':
    x, y,iterNum = explore618()
    print('试探法 在%.2f处最小值%.2f 迭代次数%d' % (x, y, iterNum))

程序还是非常简单,通过shrinkDirection变量得到上一轮缩短的方向,同时根据0.618法特性,可以复用上一轮的参数,代码运行结果如下:

618求函数最小值.png

二、函数逼近法

    函数逼近法是使用一个'尺子函数'逼近目标函数的一个片段,利用分尺子函数得到这一片段的最小值后,取最小值点作为需要迭代的下一个片段,依次重复,最后尺子函数最小值会收敛于域目标函数的最小值点。可以把每个片段尺子函数可以理解为函数空间的基,用多个尺子函数逼近目标函数的过程可以理解为用多个基来拟合目标函数,在调和分析中有一种方法叫小波分析,通过伸缩信号的尺度来拟合目标信号,他们所用的思想都是一样的。函数逼近法有很多种,常用的牛顿法、二次函数逼近法、抛物线法、插值法等,这些算法的核心思想都可以用下面的图来说明:

函数逼近 复制.png

上图f(x)是目标函数,首先构建一个尺子函数s1(x)与目标函数相切于一点x0,求出函数s1(x)最小值点为x1,在x1处再构建一个函数s2(x),使函数s2(x)与目标函数相切于点x1,同之前步骤一样,求出此时函数s2(x)最小值点x2,不断迭代后可以在第k步得到函数sk(x),函数sk(x)最小值收敛于目标函数的最小值。

余下文章链接:一维搜索

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值