在上节中本教程介绍了迭代搜索的基本步骤。考虑基本步骤中的每一步的基本元素:步长、下降方向和终止准则,其中终止准则是我们已经明确给出的,而步长和下降方向可以是任意的。但任意并不代表随机,一个随机的迭代搜索算法是无法保证收敛性的。步长和下降方向需要我们针对每一步搜索到的点的情况来求解,不仅要保证算法的收敛性,还要使得算法具有尽可能快的收敛速度。

在本节中本教程将介绍迭代搜索过程中步长的计算方法,而下降方向的计算方法会在接下来几节内给出。

1 步长的精确搜索

若我们已经知道了一个下降方向每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习,就只需要求参数每个人的步长 怎么机器学习 步长的计算方法_机器学习_02使其满足一维优化问题每个人的步长 怎么机器学习 步长的计算方法_python_03的解,令每个人的步长 怎么机器学习 步长的计算方法_python_04,则每个人的步长 怎么机器学习 步长的计算方法_算法_05,求解该线性方程组即可。

对于简单的方程,精确搜索是非常快速有效甚至有现成结论的。例如对于任意二次函数每个人的步长 怎么机器学习 步长的计算方法_人工智能_06(黑森矩阵G中值任意所以可以表示任意二次函数),有每个人的步长 怎么机器学习 步长的计算方法_机器学习_07。(证明见附录)

但我们知道,计算机求解线性方程组的方法是高斯消元法,这是一个时间复杂度为每个人的步长 怎么机器学习 步长的计算方法_机器学习_08的算法。不仅对于高维情况耗时长,就算是低维情况、单次求解的耗时可以忍受,当我们把求步长的算法整合进整个迭代算法体系中、在每次迭代时都求解步长时,积累起来就是一个巨大的时间开销。所以,如果目标函数较为复杂,我们不能得出与任意二次函数的步长求解相似的结论时,我们通常使用非精确搜索

2 步长的非精确搜索

2.1 Armijo线搜索

考虑泰勒展开每个人的步长 怎么机器学习 步长的计算方法_人工智能_09,去掉极小项,我们可以在每个人的步长 怎么机器学习 步长的计算方法_人工智能_10点处找到每个人的步长 怎么机器学习 步长的计算方法_算法_11的一条切线每个人的步长 怎么机器学习 步长的计算方法_人工智能_12

每个人的步长 怎么机器学习 步长的计算方法_算法_13

如图所示的曲线为每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习方向上函数的截线。结合图像不难理解,若局部为凸函数,则局部最优解出现在过每个人的步长 怎么机器学习 步长的计算方法_人工智能_15点平行于每个人的步长 怎么机器学习 步长的计算方法_人工智能_16轴的直线与切线每个人的步长 怎么机器学习 步长的计算方法_算法_17所夹范围之间

我们让每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_18向着平行于每个人的步长 怎么机器学习 步长的计算方法_机器学习_02轴的直线方向旋转一个角度得到每个人的步长 怎么机器学习 步长的计算方法_python_20,使每个人的步长 怎么机器学习 步长的计算方法_python_20每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_18和平行于每个人的步长 怎么机器学习 步长的计算方法_机器学习_02轴的直线所夹。其具体方法是在斜率上乘上一个每个人的步长 怎么机器学习 步长的计算方法_python_24,那么如图红色部分的点比起每个人的步长 怎么机器学习 步长的计算方法_人工智能_15将更接近局部最优解

每个人的步长 怎么机器学习 步长的计算方法_人工智能_26

这样我们就使得函数的值在我们选取的方向上有了一定程度的下降。也许我们不能一次求出最优解,但只要我们不断迭代,并每次都保证搜索方向为下降方向,就能使得Armijo线搜索收敛到该方向上的一个局部最优解。

例如,考虑最基本的情况,若函数只存在每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习方向及其反方向,在红色部分选取任意一个点(比如下降方向上每个人的步长 怎么机器学习 步长的计算方法_python_20每个人的步长 怎么机器学习 步长的计算方法_算法_29的第一个交点)作为每个人的步长 怎么机器学习 步长的计算方法_机器学习_30,寻找下降方向并重复上述过程,最终就会以如图所示的形式收敛到最优解。

每个人的步长 怎么机器学习 步长的计算方法_python_31

因此Armijo线搜索的关键在于找到一个位于红色区域内的点。其具体方法是先假设一个步长每个人的步长 怎么机器学习 步长的计算方法_机器学习_02,若不满足Armijo线性搜索条件就缩短该步长,直到满足线性搜索条件。因为我们保证了每个人的步长 怎么机器学习 步长的计算方法_python_20的斜率小于每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_18,所以这样的步长必定是存在的,结合图像也不难理解。

Armijo线搜索条件:给定每个人的步长 怎么机器学习 步长的计算方法_python_35,计算每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_36满足每个人的步长 怎么机器学习 步长的计算方法_人工智能_37

步骤:

  1. 选取一个参数每个人的步长 怎么机器学习 步长的计算方法_python_38
  2. 每个人的步长 怎么机器学习 步长的计算方法_算法_39,若每个人的步长 怎么机器学习 步长的计算方法_python_40满足线性搜索条件,则得到每个人的步长 怎么机器学习 步长的计算方法_python_40
  3. 每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_42,若每个人的步长 怎么机器学习 步长的计算方法_python_40满足线性搜索条件,则得到每个人的步长 怎么机器学习 步长的计算方法_python_40
  4. 每个人的步长 怎么机器学习 步长的计算方法_人工智能_45
  5. 每个人的步长 怎么机器学习 步长的计算方法_python_40满足线性搜索条件,则得到每个人的步长 怎么机器学习 步长的计算方法_python_40,否则转4

2.2 Wolfe-Powell搜索

在Armijo搜索的条件基础上增加防止步长过小的条件,使得每个人的步长 怎么机器学习 步长的计算方法_人工智能_48处曲线切线斜率每个人的步长 怎么机器学习 步长的计算方法_算法_49具有下界每个人的步长 怎么机器学习 步长的计算方法_python_50。在之后的教程中我们会提到,这使得算法收敛性得到保证

为保证每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_36的存在性,通常取每个人的步长 怎么机器学习 步长的计算方法_机器学习_52

每个人的步长 怎么机器学习 步长的计算方法_python_53

则有Wolfe-Powell线搜索条件:给定每个人的步长 怎么机器学习 步长的计算方法_人工智能_54,计算每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_36满足每个人的步长 怎么机器学习 步长的计算方法_人工智能_56

步骤:

  1. 每个人的步长 怎么机器学习 步长的计算方法_算法_39满足Wolfe-Powell线搜索条件,则取每个人的步长 怎么机器学习 步长的计算方法_算法_39
  2. 给定常数每个人的步长 怎么机器学习 步长的计算方法_机器学习_59每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_60,令每个人的步长 怎么机器学习 步长的计算方法_人工智能_61是集合每个人的步长 怎么机器学习 步长的计算方法_人工智能_62中满足条件1的最大者,令i=0
  3. 每个人的步长 怎么机器学习 步长的计算方法_算法_63满足条件2,则取每个人的步长 怎么机器学习 步长的计算方法_机器学习_64,否则令每个人的步长 怎么机器学习 步长的计算方法_算法_65
  4. 每个人的步长 怎么机器学习 步长的计算方法_人工智能_66是集合每个人的步长 怎么机器学习 步长的计算方法_python_67中满足条件1的最大者,令每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_68,转步3

这个搜索过程可以直观地使用下图理解:

每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_69

2.3 强条件的Wolfe-Powell搜索

在Wolfe-Powell搜索的条件基础上增加防止步长过大的条件,使得每个人的步长 怎么机器学习 步长的计算方法_人工智能_48处曲线切线斜率每个人的步长 怎么机器学习 步长的计算方法_算法_49具有上界每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_72,也就是说条件转化为了:给定每个人的步长 怎么机器学习 步长的计算方法_人工智能_54,计算每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_36满足每个人的步长 怎么机器学习 步长的计算方法_python_75

步骤:

  1. 每个人的步长 怎么机器学习 步长的计算方法_算法_39满足Wolfe-Powell线搜索条件,则取每个人的步长 怎么机器学习 步长的计算方法_算法_39
  2. 给定常数每个人的步长 怎么机器学习 步长的计算方法_机器学习_59每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_60,令每个人的步长 怎么机器学习 步长的计算方法_人工智能_61是集合每个人的步长 怎么机器学习 步长的计算方法_人工智能_62中满足条件1和条件3的最大者,令i=0
  3. 每个人的步长 怎么机器学习 步长的计算方法_算法_63满足条件2,则取每个人的步长 怎么机器学习 步长的计算方法_机器学习_64,否则令每个人的步长 怎么机器学习 步长的计算方法_算法_65
  4. 每个人的步长 怎么机器学习 步长的计算方法_人工智能_66是集合每个人的步长 怎么机器学习 步长的计算方法_python_67中满足条件1和条件3的最大者,令每个人的步长 怎么机器学习 步长的计算方法_每个人的步长 怎么机器学习_68,转步3

一般情况下的步长计算问题,只需要用普通的Wolfe-Powell搜索即可。而强条件的Wolfe-Powell搜索则在一些特殊的下降算法中有用武之地,这在我们之后的教程中会提到。

代码实现

本博客所有代码在https://github.com/HarmoniaLeo/optimization-in-a-nutshell开源,如果帮助到你,请点个star,谢谢这对我真的很重要!

你可以在上面的GitHub链接或本文集的第一篇文章深入浅出最优化(1) 最优化问题概念与基本知识中找到Function.py和lagb.py

Armijo线搜索:

import numpy as np
from Function import Function	#定义法求导工具
from lagb import *	#线性代数工具库

#假设d已经给出
a=1	#步长初值
beta1=1	#β值
rho=0.55	#ρ1值
tar=Function(myFunc)	#初始化函数
if not (tar.value(x+a*d)<=tar.value(x)+rho*a*dot(turn(tar.grad(x)),d):
    a=beta1
    while tar.value(x+a*d)>tar.value(x)+rho*a*dot(turn(tar.grad(x)),d)):
        a*=rho

Wolfe-Powell搜索:

import numpy as np
from Function import Function	#定义法求导工具
from lagb import *	#线性代数工具库

#假设d已经给出
a=1	#步长初值
beta1=1	#β值
rho=0.55	#ρ1值
sigma=0.4	#σ值
tar=Function(myFunc)	#初始化函数
if not (tar.value(x+a*d)<=tar.value(x)+rho*a*dot(turn(tar.grad(x)),d) and dot(turn(tar.grad(x+a*d)),d)>=sigma*dot(turn(tar.grad(x)),d)):
        a=beta1
        while tar.value(x+a*d)>tar.value(x)+rho*a*dot(turn(tar.grad(x)),d):
            a*=rho
        while dot(turn(tar.grad(x+a*d)),d)<sigma*dot(turn(tar.grad(x)),d):
            a1=a/rho
            da=a1-a
            while tar.value(x+(a+da)*d)>tar.value(x)+rho*(a+da)*dot(turn(tar.grad(x)),d):
                da*=rho
            a+=da

强条件的Wolfe-Powell搜索:

import numpy as np
from Function import Function	#定义法求导工具
from lagb import *	#线性代数工具库

#假设d已经给出
a=1	#步长初值
beta1=1	#β值
rho=0.55	#ρ1值
sigma=0.4	#σ值
tar=Function(myFunc)	#初始化函数
if not (tar.value(x+a*d)<=tar.value(x)+rho*a*dot(turn(tar.grad(x)),d) and np.abs(dot(turn(tar.grad(x+a*d)),d))>=sigma*dot(turn(tar.grad(x)),d)):
        a=beta1
        while tar.value(x+a*d)>tar.value(x)+rho*a*dot(turn(tar.grad(x)),d) and dot(turn(tar.grad(x+a*d)),d)>-sigma*dot(turn(tar.grad(x)),d):
            a*=rho
        while dot(turn(tar.grad(x+a*d)),d)<sigma*dot(turn(tar.grad(x)),d):
            a1=a/rho
            da=a1-a
            while tar.value(x+(a+da)*d)>tar.value(x)+rho*(a+da)*dot(turn(tar.grad(x)),d) and dot(turn(tar.grad(x+a*d)),d)>-sigma*dot(turn(tar.grad(x)),d):
                da*=rho
            a+=da

附录

二次函数步长求法:

对于每个人的步长 怎么机器学习 步长的计算方法_机器学习_88

每个人的步长 怎么机器学习 步长的计算方法_人工智能_89