找回密码
 立即注册
查看: 295|回复: 0

最优化原理与算法复习

[复制链接]
发表于 2022-5-10 14:55 | 显示全部楼层 |阅读模式
一、无约束优化

1 线搜索

线搜索类算法的数学表述为:给定当前迭代点 ,首先通过某种算法选取向量 ,之后确定正数 ,则下一步的迭代点可写作


我们称  为迭代点  处的搜索方向,为相应的步长.这里要求  是一个下降方向,即


这个下降性质保证了沿着此方向搜索函数 的值会减小.线搜索类算法的关键是如何选取一个好的方向 以及合适的步长 .
首先讨论如何选取适当的步长.
1.1 非精确线搜索

1.1.1 线搜索准则
下面介绍的线搜索准则都是单调线搜索,还有一些非单调线搜索准则,这里不加介绍

  • Armijo准则
Armijo准则对步长作了本质要求,即保证每一步迭代充分下降。
定义: 设是点处的下降方向,若

则称步长满足Armijo准则,其中是一个常数.
但Armijo准则并不能保证迭代能够顺利进行,例如 就是一个满足Armijo准则的步长。因此常常需要其他准则来配合Armijo准则使用。下面列举两种准则。

  • Goldstein-Armijo准则
    为了克服 Armijo 准则的缺陷,我们需要引入其他准则来保证每一步 的  不会太小。
    定义: 设是点处的下降方向,若

    则称步长 满足 Goldstein 准则,其中 .
# Goldstein-Armijo一维线搜索


  • Wolfe-Armijo准则
Goldstein准则能够保证函数值充分下降,但是它可能避开了最优函数值,为此我们引入Armijo-Wolfe准则。
定义: 设是点处的下降方向,若

则称步长  满足Wolfe准则,其中 为给定的常数且 .
#Wolfe-Armijo一维搜索
1.1.2 线搜索算法

  • 回退法
1.2 精确线搜索

1.2.1 试探法

  • 黄金分割法
黄金分割法是一种区间收缩法,其主要用于求解单峰函数的极值问题。其利用了单峰函数的性质,排除极值不可能存在的区间,从而达到逐渐缩小目标区间的效果。
求极小值的黄金分割法具体实现流程如下:

  • 给定 .
  • 计算 .
  • ,停止,输出 ;否则转(4).
  • 计算 .
  • 如果 ,令 , 否则令 ,转(3).
#黄金分割法
def goldenSearch(a,b,fun,epsilon = 0.01):
    x1 = a + 0.382 * (b-a)
    x2 = a + 0.618 * (b-a)
    f1 = fun(x1)
    f2 = fun(x2)
    while b-a > epsilon:
        print('a={},b={},x1={},x2={}'.format(a,b,x1,x2))
        if f1 < f2:
            b = x2
            x2 = x1
            x1 = a + 0.382 * (b - a)
            f1 = fun(x1)
            f2 = fun(x2)
        else:
            a = x1
            x1 = x2
            x2 = a + 0.618 * (b - a)
            f1 = fun(x1)
            f2 = fun(x2)
    return (b+a)/2, fun((b+a)/2)

if __name__ == '__main__':
    fun = lambda x: 2*x**2 - x - 1
    print(goldenSearch(-10,10,fun,0.01))

  • 斐波那契法
斐波那契法是分割法求解一维极小值问题的最优策略,而黄金分割法只是近似最优。
求极小值的斐波那契法实现流程如下。
#斐波那契法
import math
class Fibs:
    def __init__(self):
        self.a = 0
        self.b = 1
    def __next__(self):
        self.a, self.b = self.b, self.a + self.b
        return self.a
    def __iter__(self):
        return self
def FibsSearch(a,b,fun,epsilon = 0.01,delta = 0.001):
    ctrl = math.ceil((b-a)/epsilon)
    i = 0
    fibs = Fibs()
    F = []
    for f in fibs:
        if f > ctrl:
            break
        else:
            F.append(f)
            i += 1
    F.insert(0,0)
    n = len(F) - 1

    x1 = a + F[n-2]/F[n] * (b-a)
    x2 = a + F[n-1]/F[n] * (b-a)
    f1 = fun(x1)
    f2 = fun(x2)
    print(a, '\t', b, '\t', fun(x1), '\t', fun(x2))

    for k in range(1,n-1):
        if k == n-2:
            i = k
            break
        if f1 > f2:
            a = x1
            x1 = x2
            x2 = a + F[n-k-1]/F[n-k] * (b-a)
            f1 = fun(x1)
            f2 = fun(x2)
        else:
            b = x2
            x2 = x1
            x1 = a + F[n-k-2]/F[n-k] * (b-a)
            f1 = fun(x1)
            f2 = fun(x2)
        print(a,'\t', b,'\t', fun(x1),'\t', fun(x2))
    k = i
    x1 = x1
    x2 = x1 + delta
    f1 = fun(x1)
    f2 = fun(x2)
    if f1 > f2:
        a = x1
    else:
        b = x2
    print(a,'\t',b,'\t',fun(x1),'\t',fun(x2))
    return a,b,fun(x1),fun(x2)
if __name__ == '__main__':
    fun = lambda x: 2 * x ** 2 - x - 1
    print(FibsSearch(-1,1,fun,0.16,0.01))
1.2.2 函数逼近法

  • 牛顿法
我们首先介绍解方程的牛顿迭代法,即常说的切线迭代法,其选取一个可微函数上的初始点 ,在其处作切线,在切线与 轴交点处作垂线与函数得到一个新的交点作为 ,如此不断迭代。
容易得到牛顿迭代法的迭代公式为

而极值优化中的牛顿法则可以看作是对 通过切线法求解零点,从而求解函数的驻点,这要求函数是二阶可微的。
很明显牛顿迭代法是一个局部算法,初始点的选取对算法的收敛性和收敛速度有很大影响
牛顿迭代法的计算步骤:


  • 取初始点 ,允许误差 ,计数器 .
  • ,停止迭代,得到 .
  • 否则,根据迭代公式计算 ,置 ,回到(2).


  • 割线法
  • 抛物线法
本文使用 Zhihu On VSCode 创作并发布
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 11:35 , Processed in 0.085436 second(s), 23 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表