深入浅出最优化(1) 最优化问题概念与基本知识

1 最优化问题

1.1 什么是最优化问题

最优化问题大体上分为连续最优化问题和离散最优化问题两种。后者涉及到离散数学、组合数学等学科,属于计算机专业的专业课程,而前者的雏形在微积分课程中,甚至在高中、初中、小学的数学课堂上就有所涉及。

我们还记得求一个定义域内连续可微的一元实函数的最小值点的求解方法:求导,寻找导数为0的点,再求二阶导,这些点当中二阶导大于0的点是我们需要的极值点,再将这些极点对应的函数值进行对比,函数值最小的点就是我们需要的最小值点。

上述问题就是一个最基本的最优化问题,但它已经充分描述了最优化问题的基本目标:求解函数的最小值点。当然,求解最大值点的方法也是相同的,因此我们再讨论最优化问题时只讨论最小化问题。

若函数定义域为R,则该最优化问题为无约束最优化问题。否则,就是约束最优化问题

下面,针对多元函数,我们提出最优化问题规范化的描述。

1.2 名词与符号

  • 最优点x^*
  • 最优值f(x^*)
  • 最优解(x^*,f(x^*))^T
  • 可行域D,对应于基本问题中的定义域
  • 梯度g=\nabla f(x),对应于基本问题中的一阶导数
  • 黑森矩阵G=\nabla^2f(x),对于n元函数,(i,j)\quad i,j\in n位置的值为\frac{\partial^2 f(x)}{\partial x_i\partial x_j},对应于基本问题中的二阶导数
  • 局部最优解:在x^*附近一个邻域内f(x^*)最小,对应基本问题中的极值点
  • 全局最优解:在Df(x^*)最小,对应基本问题中的最小值点

1.3 最优解条件

  1. 一阶必要条件:f(x)一阶连续可微且g^*=\nabla f(x^*)=0x^*为f(x)的局部最优解的必要条件。满足g^*=\nabla f(x^*)=0的点称为驻点。驻点分为:极小点,极大点,鞍点
在这里插入图片描述

仅从三维空间来看,梯度为0的几何意义是该处曲面水平。当然这个曲面还可以拓展到更高维的空间中,在此不再赘述

  1. 二阶充分条件:f(x)二阶连续可微且\nabla f(x^*)=0, \nabla^2f(x^*)正定,是x^*为f(x)的严格局部最优解的充分条件。如果说一阶条件刻画了f(x)在x处切平面的法向,二阶条件就刻画了曲面的弯曲方向,而\nabla^2f(x^*)正定代表了此处曲面向上弯曲

以上两个条件虽然拓展到了高维,但实际上和一元函数最优化问题的条件是通过1.2中给出的对应关系对应的,结合起来就不难理解

2 用计算机求解问题

2.1 迭代搜索

我们最终的目标是要实现让计算机代替我们去寻找最优化问题的解。我们不能指望计算机具有和我们一样的智能、对于一个方程可以使用人类总结出来的诸如分离变量之类的各种方法去求解。我们只能使用数值方法,通过循环迭代解出一个逼近于最优解的答案。这个过程称为迭代搜索

我们考虑如图所示的一个三维曲面,x_k是当前我们所在点。假如这个点不是我们需要的最优解,我们就需要移动到下一个点。移动需要确定方向和距离,因此我们有迭代搜索的基本元素如下:

  • 步长:迭代搜索第k步的长度,用\alpha_k表示

  • 下降方向:迭代搜索第k步的方向,用d_k表示,沿该方向函数值需要下降,这样才能保证算法的收敛性。其中可行方向表示沿着该方向搜索,存在使得下一个点不超出可行域的步长

在这里插入图片描述
  • 终止准则:考虑一阶必要条件,即\nabla f(x)=0,我们将这个条件作为迭代终止的准则。如果我们当前所在点满足准则,就不需要再寻找下一个点了。当然,对于搜索算法来说,我们不能保证我们一定可以通过有限步的搜索找到精确地满足\nabla f(x)=0的点,而我们在实际工程运用中对于最小值点的要求也并非是绝对精确的。因此,引入一个精确度\epsilon,只要梯度满足||g(x_k)||\leq \epsilon即可认为满足了终止准则。

根据基本元素,我们可以得出n元函数迭代搜索的步骤:

  1. 给出x_0\in R^n,0\leq \epsilon<<1,k=0
  2. 如果在x_k终止准则被满足,停止迭代
  3. 确定x_k下降方向d_k
  4. 确定步长因子\alpha_k
  5. x_{k+1}=x_k+\alpha_kd_k,转步骤2

2.2 质量评估

  1. 收敛性:对于迭代序列x^{(k)},严格的收敛定义要求k趋近于正无穷时等于最优点,弱化的收敛定义要求k趋近于无穷时一阶偏导向量的范数为0
  2. 收敛速度x^{(k)}为p阶收敛,则\displaystyle\lim_{k→∞}\frac{||x^{(k+1)}-x^*||}{||x^{(k)}-x^*||^P}=\beta<+∞
    1. p=1,0<\beta<1,则算法线性收敛
    2. p=1,\beta=0,则算法超线性收敛
    3. p=2,\beta>0,则算法二阶收敛。二阶收敛必定超线性收敛,且二阶收敛的算法收敛速度高于线性收敛的算法
  3. 二次终止性:若某个算法对于任意的正定二次函数,从任意初始点出发,都能经过有限步迭代达到极小值,则称算法具有二次终止性

一个可行的收敛算法必须满足收敛性,收敛速度越快的算法性质越好,而具有二次终止性的算法可以在求解二次函数最优化问题时具有广泛的应用价值。但证明这些性质并不作为本系列教程的重点。本教程会给出每一种算法性质的结论与相关证明教程链接,有兴趣的读者可以自行查阅

3 最小二乘问题——无约束最优化问题实例

点列的曲线拟合是我们高中开始就接触过的问题。为了寻找一个待定系数的函数,可以以最小的误差去描述点列,我们需要用到最小二乘法。有关最小二乘法可以参阅:https://www.zhihu.com/question/37031188

最小二乘法是我们研究无约束最优化问题的一个出色的实例。它具有广泛的应用价值,而且目标函数的局部最优解就是全局最优解。我们在接下来的无约束最优化问题部分将针对一个最小二乘法例题进行研究。

例题:

min\displaystyle\sum_{i=1}^{11}(y_i-\hat{f}(x,t_i))^2,\hat{f}(x,t)=\frac{x_1(t^2+x_2 t)}{t^2+x_3t+x_4}

在这里插入图片描述

给出了11组(t_i,y_i)的数据,要求我们通过最小二乘法解出x_i,i\in1,2,3,4,使得函数\hat{f}(x,t)可以最好地拟合y=f(t)

代码实现

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

本次代码实现内容是梯度、梯度二范数、黑森矩阵等最优化问题基本件的python数值解法,以及简化的python线性代数库

梯度、梯度二范数、黑森矩阵求法参考自博客,有修改:https://www.cnblogs.com/kisetsu/p/9145393.html

制作一个文件Fuction.py,在里面写入:

import numpy as np

class Function:
    def __init__(self, _f):
        self.fun = _f

    def value(self, val):
        return self.fun(val)

    def part(self, var_index, val):
        a = self.fun(val)
        b = a + 1
        i = 0
        e = 2 ** 10 - 1
        e1 = 2 ** 10
        while 10 ** (-6) < e < e1 or i > -6:
            e1 = e
            a = b
            val_ = list(val)
            val_[var_index] += 10 ** i
            m = self.fun(val_)
            n = self.fun(val)
            b = (m - n) / 10 ** i
            i -= 2
            e = abs(b - a)
        return a

    def part_2(self, x_index, y_index, val):
        return self.__diff_(x_index).__diff_(y_index).value(val)

    def diff(self, val):
        a = self.fun(val)
        b = a + 1
        i = 0
        e = 2 ** 10 - 1
        e1 = 2 ** 10
        while 10 ** (-6) < e < e1 or i > -6:
            e1 = e
            a = b
            val_ = val + 10 ** i
            m = self.fun(val_)
            n = self.fun(val)
            b = (m - n) / 10 ** i
            i -= 2
            e = abs(b - a)
        return a

    def grad(self, val):
        g = np.array(val).astype('float')
        for i in range(0, g.size):
            g[i] = self.part(i, val)
        return np.array(g)

    def __diff_(self, index):
        def diff_f(vals):
            vals_ = list(vals)
            vals_[index] = vals_[index] + 10 ** (-6)
            m = self.fun(vals_)
            n = self.fun(vals)
            return (m - n) / 10 ** (-6)
        return Function(diff_f)

    def hesse(self, val):
        v = np.mat(val)
        G = np.mat(np.dot(v.T, v)).astype('float')
        for i in range(0, v.size):
            for j in range(0, v.size):
                p = self.part_2(i, j, val)
                G[i, j] = p
        G=np.array(G)
        return G
    
    def norm(self, val):
        s = 0
        for x in self.grad(val):
            s += x ** 2
        return np.sqrt(s)

在之后的每个方法实现中,我们都会用到Fuction.py

from Function import Function

tar=Function(func)  #func是一个以列表为参数的多元函数
val=tar.val(para)   #传入参数获取值
diff=tar.diff(para) #一元函数求导
part=tar.part(index,para)   #对第index个参数求导
grad=tar.grad(para) #求梯度数组
hesse=tar.hesse(para)   #求hesse阵
norm=tar.norm(para) #求梯度范数

另外制作一个文件lagb.py,在里面写入:

import numpy as np

def turn(a):    #转置
    if len(a.shape)==1:
        a=a.reshape((1,a.shape[0]))
        return a
    else:
        return np.array(np.mat(a).T)

def dot(a,b):   #点乘
    if len(a.shape)==1:
        a=a.reshape((a.shape[0],1))
    if len(b.shape)==1:
        b=b.reshape((b.shape[0],1))
    res=np.array(np.mat(a)*np.mat(b))
    if res.shape==(1,1):
        return res[0][0]
    else:
        if res.shape[1]==1:
            return res.squeeze()
        else:
            return res

def muldot(*args):  #连乘
    res=args[0]
    for i in range(1,len(args)):
        res=dot(res,args[i])
    return res

def rev(a): #求逆
    return np.array(np.mat(a).I)

在之后的每个方法实现中,我们也都会用到lagb.py

from lagb import *

#输入参数可以为向量或矩阵,即numpy创建的数组
#用numpy创建的一维数组会默认为列向量
a=turn(a)   #求转置
c=dot(a,b)  #点乘,视情况会返回向量、矩阵、数值
d=dot([a,b,c])  #连续的点乘
b=rev(a)    #求逆矩阵
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350