zoukankan      html  css  js  c++  java
  • 梯度寻优

    上接 凸优化基础

    扩展:机器学习中的几个概念的关系

    2.1 逐次逼近法

    使用主元消去法求解线性方程组 (Ax = b) 相信大家都不陌生,但是对于 (A) 的阶数很大且零元素很多的大型稀疏矩阵方程组,使用主元消去法求解将会是一个很大的挑战。鉴于此,逐次逼近法 (或称为迭代法[1]) 提供了解决策略。

    下面我们来看看迭代法的具体操作:


    首先将 (Ax=b) 改写为 (x = Bx + f), 使用公式:

    [x^{k+1} = Bx^k + f ]

    其中 (k) 为迭代次数 ((k=0, 1, 2, cdots))

    (displaystylelim_{k o infty} x^k) 存在 (记作 (x^*)),称此迭代法收敛。显然 (x^*) 就是方程组的解,否则称此迭代法发散。


    2.1.1 研究数列的收敛性

    引入误差向量:

    [epsilon^{k+1} = x^{k+1} - x^* ]

    我们可以得到

    [epsilon^{k+1} = (Bx^k + f) - (Bx^* + f) = Bepsilon^k = B^kepsilon^0 ]

    故而,要研究数列 ({x^k}) 的收敛性,只需要研究 (displaystylelim_{k o infty} epsilon^k = 0)(displaystylelim_{k o infty} B^k = 0) 满足的条件。

    下面以 Numpy 的形式呈现迭代的过程与结果:

    2.1.2 消元法

    import numpy as np # 载入矩阵运算库
    A = np.array([[8, -3, 2], [4, 11, -1], [6, 3, 12]])
    b = np.array([[20], [33], [36]])
    result = np.linalg.solve(A, b)
    print('x
    ',result)
    
    x
     [[3.]
     [2.]
     [1.]]
    

    (Ax = b) 转换为:(x^{k+1}=B x^k+f)

    B = np.array([[0.0, 3.0 / 8.0, -2.0 / 8.0], 
                  [-4.0 / 11.0, 0.0, 1.0 / 11.0],
                  [-6.0 / 12.0, -3.0 / 12.0, 0.0]])
    f = np.array([[20.0 / 8.0], [33.0 / 11.0], [36.0 / 12.0]])
    
    m, n = B.shape
    
    error = 1e-7  # 误差阈值
    steps = 100  # 迭代次数
    xk = np.zeros((m, 1))  # 初始化 xk = 0
    errorlist = []  # 记录逐次逼近的误差列表
    for k in range(steps):
        xk_1 = xk  # 上一次的 xk
        xk = np.dot(B, xk) + f  # 本次 xk
        errorlist.append(np.linalg.norm(xk - xk_1))  # 计算并存储误差
        if errorlist[-1] < error:  # 判断误差是否小于阈值
            print('终止迭代数:', k + 1)  # 输出迭代次数
            break
    print(xk)  # 输出计算结果
    
    终止迭代数: 18
    [[2.99999998]
     [2.00000003]
     [1.00000003]]
    

    2.1.3 绘制误差收敛散点图

    from matplotlib import pyplot as plt
    
    
    def drawScatter(plt, mydata, size=20, color='blue', mrkr='o'):
        m, n = mydata.shape
        if m > n and m > 2:
            plt.scatter(mydata.T[0], mydata.T[1], s=size, c=color, marker=mrkr)
        else:
            plt.scatter(mydata[0], mydata[1], s=size, c=color, marker=mrkr)
    
    
    matpts = np.zeros((2, k + 1))
    matpts[0] = np.linspace(1, k + 1, k + 1)
    matpts[1] = np.array(errorlist)
    drawScatter(plt, matpts)
    plt.show()
    

    如图, 可以看出误差收敛很快, 从第四次就开始接近最终结果, 后面的若干次迭代都是对结果的微调.

    通过误差收敛与否判断解的存在性, 只要误差能够收敛, 方程组就会有解, 但若目标函数是非线性的, 为了更快的收敛, 我们需要找到收敛最快的方向 (梯度方向).

    2.2 梯度下降

    参考: 梯度下降法

    假设目标函数是一个凸函数, 在最优化方法中被表示为:

    [underset{x}{argmin} ;;f(x),;;xin mathbb{R}^n ]

    假如 (f(x))(x_0) 处可微, 则 (∇f(x_0)) 便是 (x_0) 处的变化最快的方向.

    为了求解 (f(x)) 的最小值, 可以选择任意初始点 (x_0), 从 (x_0) 出发沿着负梯度方向走, 可使得 (f(x)) 下降最快. 引入新的参数 ( ho_k) 被称为步长, 有

    [x_{k+1} = x_k - ho_kfrac{∇f(x_k)}{||∇f(x_k)||} ]

    详细见 梯度相关代码


    1. https://www.jianshu.com/p/497bb00cf657 ↩︎

  • 相关阅读:
    【模板】后缀自动机
    【模板】矩阵求逆
    【hdu5517】Triple
    【模板】多标记 LCT
    【洛谷P4172】水管局长
    【模板】LCT
    【CF786B】Legacy
    jacoco学习
    python + redis
    Python Gitlab Api 使用方法
  • 原文地址:https://www.cnblogs.com/q735613050/p/9498022.html
Copyright © 2011-2022 走看看