一维搜索、最速下降(梯度下降)与牛顿法(拟牛顿法)

一维搜索

最优化问题一般选择某一组变量,然后在满足一定的限制条件下,求出使目标值达到最优(最大或最小)的变量值。大部分时候,最优化问题都采用迭代计算的方式来求解。而大多数迭代下降算法都具有的共同点是在得到某次迭代点 x k x^k xk后,需要按照一定规则来确定一个方向 d k d^k dk,沿着该方向在直线上求函数的极小点得到下一个迭代点 x k + 1 x^{k+1} xk+1。这样不断在一维的目标函数上,求其在各迭代点的直线方向上的极小点,直到求出问题最优解的方式就被称为一维搜索,或者线搜索。其一般过程可用如下公式表示:
x k + 1 = x k + λ d k x^{k+1}=x^k+λd^k xk+1=xk+λdk
其上 d k d^k dk,表示在这一步的搜索方向,步长因子 λ λ λ决定了沿着该方向前进多远。这两者共同决定了该搜索算法的好坏。一维搜索的算法有好多种,以下介绍几种常见的。

黄金分割法

基础公式:
λ k = a k + 0.382 ( b k − a k ) λ_k=a_k+0.382(b_k-a_k ) λk=ak+0.382(bkak)
μ k = a k + 0.618 ( b k − a k ) μ_k=a_k+0.618(b_k-a_k) μk=ak+0.618(bkak)
流程如下:
在这里插入图片描述
0.618法和Fibonacci法的运作机理是一致的,且都适用于单峰函数的情形,只不过将区间长度缩短比例由常数0.618更改为了斐波那契数列。在实际应用问题中,目标函数在其定义域内很有可能不是单峰的,因此我们在使用时需要先确定其单峰区间再行计算。

牛顿法

在这里插入图片描述
牛顿法迭代法的基本思想是利用二阶泰勒展开在极小点附近来近似目标函数,最终解出极小点的一个近似值。其主要解算步骤如下:
x k + 1 = x k − f ′ ( x k ) / f ′ ′ ( x k ) x^{k+1}=x^k-f^{'}(x^k)/f^{''}(x^k) xk+1=xkf(xk)/f(xk)
在这里插入图片描述
若是初始点选择的比较靠近极小点,迭代过程就能很快地收敛,反之则有可能不收敛到极小点。

最速下降法

上文中的一维搜索可归结为单变量函数的最优化问题,也是最速下降法的基础。
x k + 1 = x k + λ d k x^{k+1}=x^k+λd^k xk+1=xk+λdk
其迭代过程中最重要的就是为下次迭代选择一个合适的方向 d k d^k dk。人们利用了梯度方向是函数值增长最快的方向的思想,来让迭代点沿着负梯度方向前进,保证函数的“最速”下降。
以下直接给出公式:
x k + 1 = x k − λ ∇ f ( x k ) x^{k+1}=x^k-λ∇f(x^k) xk+1=xkλf(xk)
在多元函数中:
∇ f ( x ) = ( ∂ f ( x ) / ( ∂ x 1 ) , … , ∂ f ( x ) / ( ∂ x n ) ) ∇f(x)=(∂f(x)/(∂x_1 ),…,∂f(x)/(∂x_n )) f(x)=(f(x)/(x1),,f(x)/(xn))
步长 λ λ λ由求解式: a r g m i n f ( x k + λ d k ) argminf(x^k+\lambda d^k) argminf(xk+λdk)得到,是一种精确步长的搜索方式。其与梯度下降法的区别也在于此,梯度下降中的步长往往是由工程师自己预先设置好的一个固定值,因此梯度下降法只是最速下降法中的一种特殊形式。

形象点地说,假设有一小球要从山顶滚到山脚,那么每次沿最陡峭(梯度)的方向向下滚是最快的。在确定了每次下降的方向的同时也需要小心地选择一个合适的步长。若是过大,可能导致迭代点发散,过小则导致收敛太慢。由于梯度为0的点是函数取极值的必要条件,却不是充分条件,所以梯度下降法最终带给我们的解,可能只是一个局部最优解:也就是我们的小球陷入了山腰上的某个小坑中无法动弹(然而事实上在机器学习中,往往梯度下降只能让loss函数下降到鞍点,甚至无法抵达局部最优解)。而随机梯度下降法则为跳出局部最优解提供了可能,如下图所示:
在这里插入图片描述
其会比较多个小球的结果,而当小球数目足够多时,其中海拔最低的那个球也就为我们带来了全局最优解。
最速下降算法还有一个局限之处是存在下图所示的锯齿现象:
在这里插入图片描述
由于最速下降法在极小化目标函数时的相邻两个搜索方向是正交的,以下给出简易证明过程:
g ( λ ) = f ( x k + λ d k ) g(\lambda)=f(x^k+\lambda d^k) g(λ)=f(xk+λdk)
为了求其在方向 d k = − ∇ f ( x k ) d^k=-∇f(x^k) dk=f(xk)上的极小点,需要先确定步长,令:
g ′ ( λ ) = ∇ f ( x k + λ k d k ) T d k = 0 g^{'}(\lambda)=∇f(x^k+\lambda_k d^k)^Td^k=0 g(λ)=f(xk+λkdk)Tdk=0
可得:
− ∇ f ( x k + 1 ) T ∇ f ( x k ) = 0 -∇f(x^{k+1})^T ∇f(x^k)=0 f(xk+1)Tf(xk)=0
即方向 d k + 1 d^{k+1} dk+1与方向 d k d^k dk正交。所以使用最速下降法得到的迭代路线往往是呈现一个之字形的走势。而当迭代点越靠近极小点,其移动的步长较小,严重影响到了收敛的速度。虽然从局部来看,每次选择的方向都是函数值下降最快的方向,但是从全局来看,锯齿现象导致当距离极小点较近时需要绕不少弯路才能收敛,反而收敛较慢。因此在计算的前中期使用梯度下降,而在接近极小点时使用其他算法进行迭代会是更理想的方案。

牛顿法与拟牛顿法

此处介绍的牛顿法是其在一维搜索中的推广形式。与最速下降法一样可用于求解一般无约束的多元优化问题。其基本思想还是采用泰勒二阶展开来拟合极小点附近的函数来进行迭代:
x k + 1 = x k − ∇ 2 f ( x k ) − 1 ∇ f ( x k ) x^{k+1}=x^k-∇^2f(x^k)^{-1}∇f(x^k) xk+1=xk2f(xk)1f(xk)
可以看到我们需要函数在迭代点处的梯度 ∇ f ( x k ) ∇f(x^k) f(xk)以及 ∇ 2 f ( x k ) ∇^2f(x^k) 2f(xk)海森矩阵的逆矩阵来进行下一步的迭代点的计算。也有许多文献证明牛顿法的收敛速度是很快的,特别对于目标函数为二次凸函数的情况来说,其只需一次迭代就能得到极小点,像这样在有限次迭代后能使函数必定达到极小点的方法我们可称其具有二次终止性。像上文中的最速下降法对一般的凸函数就不具备此性质。

但是牛顿法也有可能无法收敛,因为牛顿方向并不一定是下降的方向。因此人们提出了结合沿牛顿方向进行一维搜索的修正牛顿法。机智的小伙伴们可能注意到,无论是牛顿法还是修正牛顿法都有一个问题:他们都需要海森矩阵的逆矩阵才能进行迭代。因此针对海森矩阵为奇异矩阵,或者海森矩阵维度过高,求逆所需的计算量太庞大的情况:拟牛顿法应运而生。我们会构造一个新的对称正定矩阵来取代海森矩阵进行迭代,避免了求逆以及二次微分的计算。根据不同的构造方式还可细分成不同的子方法如:BFGS、DFP等。具体的构造方法以及推导过程有很多文献,这里不多做介绍了。

参考

陈宝林,《最优化理论与算法》。

  • 7
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在PyTorch中,您可以使用梯度下降法或拟牛顿法来最小化损失函数。下面是一个示例代码,其中使用梯度下降法(使用`torch.optim.SGD`优化器)来最小化损失函数: ```python import torch import torch.nn as nn import torch.optim as optim # 定义模型 class Model(nn.Module): def __init__(self): super(Model, self).__init__() self.linear = nn.Linear(1, 1) # 假设输入是1维,输出是1维 def forward(self, x): return self.linear(x) # 创建模型实例 model = Model() # 定义损失函数 criterion = nn.MSELoss() # 定义优化器 optimizer = optim.SGD(model.parameters(), lr=0.01) # 训练模型 num_epochs = 100 for epoch in range(num_epochs): # 假设输入和目标是一些示例数据 inputs = torch.tensor([[1.0], [2.0], [3.0], [4.0]]) targets = torch.tensor([[2.0], [4.0], [6.0], [8.0]]) # 前向传播 outputs = model(inputs) loss = criterion(outputs, targets) # 反向传播和优化 optimizer.zero_grad() loss.backward() optimizer.step() # 每一轮打印损失值 print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item())) ``` 在这个例子中,我们首先定义了一个简单的线性模型,并使用均方误差损失函数(`nn.MSELoss()`)来定义损失。然后,我们创建了一个优化器(`optim.SGD`),它将根据梯度更新模型的参数。 在训练循环中,我们使用示例数据进行前向传播,计算损失,并通过反向传播和优化器来更新模型参数。最后,我们打印每一轮的损失值。 如果您想使用拟牛顿法,可以将优化器替换为`torch.optim.LBFGS`,并调整相应的参数。 希望对您有所帮助!如有任何疑问,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值