1 下降算法中的搜索方向
1.1 下降方向的判定
根据泰勒展开,忽略极小项后,我们可以在点处找到的一条切线,这条切线的斜率是。我们不难得出结论,如果,则该方向为下降方向。
1.2 下降算法的收敛性
前面我们给出过下降算法的收敛性的定义:对于迭代序列,k趋近于无穷时一阶偏导向量的范数为0。之后我们在介绍精确搜索与非精确搜索时均强调了搜索方向必须是下降方向。事实上,如果步长由精确搜索或者Wolfe-Powell搜索产生,而每一步的搜索方向都是下降方向,则必定满足下降算法的收敛性。(证明见附录1)
因此接下来我们在研究计算搜索方向的算法时,最重要的前提就是计算出的搜索方向应当是下降方向。而步长计算则使用精确搜索、Wolfe-Powell搜索或强条件的Wolfe-Powell搜索。
2 最速梯度下降法
2.1 最速梯度下降法步骤
既然我们要寻找下降方向,我们首先想到的就是梯度的反方向。函数沿着梯度方向数值上升最快,那么沿着梯度的反方向数值下降也就最快。所以,对于每一步,将负梯度方向作为下降方向的方法,又叫最速梯度下降法。
步骤:
- 给定初始点,精度,令
- 若,则得解,算法终止
- 计算
- 计算步长
- 令,转步2
2.2 性能评估
- 收敛性:因为每一步均产生下降方向,所以必定收敛。
- 收敛速度:用正定二次函数逼近点附近的函数。若该正定二次函数黑森矩阵的所有特征值相等,则超线性收敛;其余时候线性收敛。(证明见附录2)
- 二次终止性:显然满足
- 计算量:小,只需要计算梯度
- 储存空间:小,只需要储存梯度
2.3 实战测试
对于本文集的第一篇文章深入浅出最优化(1) 最优化问题概念与基本知识中提出的最小二乘问题,的初值均在的范围内随机生成,总共生成100组起点。统计迭代成功(在1000步内得到最优解且单次步长搜索迭代次数不超过1000次)的样本的平均迭代步数、平均迭代时间和得到的最优解及残差平方和最小值。
平均迭代步数 | 平均迭代时间 | 最优解 | 残差平方和最小值 |
---|---|---|---|
234.68 | 3.31s |
3 阻尼牛顿法
3.1 阻尼牛顿法步骤
古典牛顿法的思想是用近似二次函数的极小点作为原问题的新的近似解。在处二阶泰勒展开式为,二次近似函数,且,若正定,则的极小点为的解,把二次函数的极小点作为,则,称该迭代公式为古典牛顿法的迭代公式,其中为处的牛顿方向。
如果目标函数就是二次函数,则向着牛顿方向步长为1的搜索可以直接搜索到局部最优解。但如果二次函数仅仅是目标函数的近似,则步长需要使用Wolfe-Powell搜索来求取,这时候算法被称为阻尼牛顿法。
步骤:
- 定初始点,精度,令
- 若,则得解,算法终止
- 计算步长
- 令,转步2
3.2 性能评估
- 收敛性:当且仅当每一步都有目标函数的黑森矩阵,也就是近似二次函数的黑森矩阵正定时,牛顿方向才是下降方向,所以收敛性不能保证。
- 收敛速度:若在最优解附近二阶连续可微且最优解处梯度为0、黑森矩阵正定,则算法超线性收敛。特别地,若目标函数在最优解处二阶李普希兹连续,则算法二阶收敛。(证明见附录3)
- 二次终止性:显然满足
- 计算量:大,需要计算黑森矩阵,在变量数目多时计算量大
- 储存空间:大,需要储存黑森矩阵,在变量数目多时需要储存空间大
4 牛顿-梯度下降混合法
4.1 牛顿-梯度下降混合法步骤
由于我们不能保证牛顿法产生下降方向,但又希望能够借助牛顿法的二阶收敛性提高最速梯度下降法的收敛速度,我们可以将两者进行融合。对于牛顿法无法产生下降方向的时刻,使用最速梯度下降法来产生下降方向。
步骤:
- 定初始点,精度,令
- 若,则得解,算法终止
- 若,取
- 计算步长
- 令,转步2
4.2 实战测试
对于本文集的第一篇文章深入浅出最优化(1) 最优化问题概念与基本知识中提出的最小二乘问题,的初值均在的范围内随机生成,总共生成100组起点。统计迭代成功率(在1000步内得到最优解且单次步长搜索迭代次数不超过1000次)、平均迭代步数、平均迭代时间和得到的最优解及残差平方和最小值。
平均迭代步数 | 平均迭代时间 | 最优解 | 残差平方和最小值 |
---|---|---|---|
56.0 | 1.02s |
代码实现
本博客所有代码在https://github.com/HarmoniaLeo/optimization-in-a-nutshell开源,如果帮助到你,请点个star,谢谢这对我真的很重要!
你可以在上面的GitHub链接或本文集的第一篇文章深入浅出最优化(1) 最优化问题概念与基本知识中找到Function.py和lagb.py
最速下降法:
import numpy as np
from Function import Function #定义法求导工具
from lagb import * #线性代数工具库
n=2 #x的长度
def myFunc(x): #x是一个包含所有参数的列表
return x[0]**2 + 2*x[1]**2 + 2*x[0] - 6*x[1] +1 #目标方程
x=np.zeros(n) #初值点
rho=0.6
beta=1
sigma=0.4
e=0.001
k=0
tar=Function(myFunc)
while tar.norm(x)>e:
d=-tar.grad(x)
a=1
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=beta
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
x+=a*d
k+=1
print(k)
print(x)
牛顿-梯度下降混合法:
import numpy as np
from Function import Function #定义法求导工具
from lagb import * #线性代数工具库
from scipy import linalg
n=2 #x的长度
def myFunc(x): #x是一个包含所有参数的列表
return x[0]**2 + 2*x[1]**2 + 2*x[0] - 6*x[1] +1 #目标方程
x=np.zeros(n) #初值点
rho=0.6
beta=1
e=0.001
sigma=0.4
k=0
tar=Function(myFunc)
while tar.norm(x)>e:
try:
d=linalg.solve(tar.hesse(x),-tar.grad(x))
if tar.value(x)-tar.value(x+d)<0:
d=-tar.grad(x)
except Exception:
d=-tar.grad(x)
a=1
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=beta
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
x+=a*d
k+=1
print(k)
print(x)
附录
- 记向量和的夹角为,则有
给出下面的基本假设:连续可微且有下界,且李普希兹连续,即存在常数,使得
则有定理,若序列由下降算法产生,其中步长由精确搜索或Wolfe-Powell搜索产生,则。特别地,若存在常数使得,则。这个定理说明了产生的方向与负梯度方向夹角小于时,可以保证算法收敛性。
下面根据假设证明该定理:由Wolfe-Powell搜索条件及假设,我们有,即可得。这里,进一步由Wolfe-Powell搜索第一个条件,得
将上面的不等式左右两边从到相加,并注意到有下界,可以得到定理第一条成立,由无穷级数收敛的必要条件可以得到第二条定理成立。
最速梯度下降法收敛速度证明:https://blog.csdn.net/weixin_43010548/article/details/97619095
-
牛顿法收敛速度证明:
提出定理:设在的某个邻域内二次连续可微且满足,正定,则存在常数,使得当时,由单位步长牛顿法产生的序列超线性收敛于,此外,若在李普希兹连续,则序列二次收敛于。