最小二乘法(基本原理+代码解析)

前言:

在工程应用中,经常会遇到目标函数是若干个函数平方和的最优化问题。

min S(x)=\sum_{i=1}^{m}f_{i}^{2}(x),x\in R^{n},m> n

这类问题称为最小二乘问题。

本章节讲述无约束规划中的最小二乘法。


线性最小二乘法:

当 f_{i}(x) 是线性函数时,即 f_{i}(x)=\sum_{j=1}^{n}a_{ij}x_{j}-b_{j},i=1,2,...,m ,如果令 A=\begin{pmatrix} a_{11} & a_{12} &... &a_{1n} \\ a_{21}& a_{22} & ... & a_{2n} \\ a_{31}& a_{32} & ... &a_{3n} \\ a_{41}& a_{42} &... & a_{4n} \end{pmatrix}b=\begin{pmatrix} b_{1}\\ b_{2} \\ ... \\ b_{m} \end{pmatrix}f(x)=(f_{1}(x),f_{2}(x),...,f_{m}(x))^{T}

S(x)=f(x)^{T}f(x)=(Ax-b)^{T}(Ax-b)=\left | \left | Ax-b \right | \right |^{2}

原问题可以表示为: minS(x)=\left | \left | Ax-b \right | \right |^{2}

求解该方程就变成了寻找一个向量 x ,使得 \left | \left | Ax-b \right | \right |^{2} 达到最小。

如果向量 x^{*} 能够使得 \left | \left | Ax-b \right | \right |^{2} 达到最小,即对与所有 x\in R^{n} 都有:

\left | \left | Ax-b \right | \right |^{2}\geq \left | \left | Ax^{*}-b \right | \right |

则称 x^{*} 为 Ax=b 的最小二乘解。当方程组 Ax=b 有解时,其解自然是一个最小二乘解;若 Ax=b 无解,则只能寻求其最小二乘解,即能够使得 Ax 和 b 之间差值的范数达到最小的向量。

下面给出两个引理:


引理1:

矩阵 A\in R^{m*n} ,m\geq n,当且仅当 rank A^{T}A=n (即方阵 A^{T}A 非奇异)时,rank A=n

引理2:

能够最小化 \left | \left | Ax-b \right | \right |^{2} 的向量 x^{*} 具有唯一性。可以通过求解方程组 A^{T}Ax=A^{T}b 得到,即 x^{*}=(A^{T}A)^{-1}A^{T}b


例题分析:

例题:求线性最小二乘问题: min\left | \left | Ax-b \right | \right |^{2} 的最优解

其中 A=\begin{pmatrix} 3 &1 \\2 &-3 \\ -1 &4 \end{pmatrix}b=\bigl(\begin{smallmatrix} 2\\-3 \\-1 \end{smallmatrix}\bigr)

解:可以直接通过公式 x^{*}=(A^{T}A)^{-1}A^{T}b 判断是否有解,

A^{T}A=\bigl(\begin{smallmatrix} 14 & -7\\ -7 &26 \end{smallmatrix}\bigr),(A^{T}A)^{T}=\frac{1}{350}\bigl(\begin{smallmatrix} 26 & 7\\ 7 &14 \end{smallmatrix}\bigr)

\bar{x}=\frac{1}{350}\bigl(\begin{smallmatrix} 26 & 7\\ 7 &14 \end{smallmatrix}\bigr)\bigl(\begin{smallmatrix} 3 &2 &-1 \\1 &-3 & 4 \end{smallmatrix}\bigr)\bigl(\begin{smallmatrix} 2\\-3 \\-1 \end{smallmatrix}\bigr)=\binom{\frac{3}{14}}{\frac{3}{10}}

又因为min\left | \left | Ax-b \right | \right |^{2}=\left | \left | A\bar{x}-b \right | \right |^{2}\neq 0

所以:方程组\left\{\begin{matrix} 3x_{1}+x_{2}=2\\ 2x_{1}-3x_{2}=-3 \\ -x_{1}+4x_{2}=-1 \end{matrix}\right. 无解


非线性最小二乘法(LM算法):

基本思想是把函数线性化,用线性最小二乘问题的解去逼近非线性最小二乘问题的解。

它通过同时利用高斯牛顿方法和梯度下降方法来解决非线性最小二乘问题。其核心思想是在每次迭

代中,根据当前参数估计计算目标函数的梯度和海森矩阵,并使用这些信息来更新模型参数。

算法步骤:

步骤1:选取初始点 x_{0},给定初始值 \alpha _{0},放大因子 \beta > 1,允许误差 \varepsilon > 0

步骤2:求出 f(x_{0}),S(x_{0}),k=0

步骤3:求出雅克比矩阵 \bigtriangledown f(x_{k})

雅克比矩阵

步骤4:如果\left | \left | \bigtriangledown f(x_{k})^{T}\bigtriangledown f(x_{k}) \right | \right |< \varepsilon,停止, x_{k} 是近似最优解;否则,转步骤5;

步骤5:构造 LM 方向,d_{k}=-[\left | \left | \bigtriangledown f(x_{k})^{T}\bigtriangledown f(x_{k}) \right | \right |+\alpha _{k}I_{n}]^{-1} \bigtriangledown f(x_{k})^{T}\bigtriangledown f(x_{k})

步骤6:计算f(x_{k}+d_{k})S(x_{k}+d_{k}),如果S(x_{k}+d_{k})< S(x_{k}) ,转步骤8;否则,转步骤7;

步骤7:放大系数,令 \alpha _{k}=\beta \alpha _{k} ,返回步骤5;

步骤8:缩小参数,令 x_{k+1}=x_{k}+d_{k},\alpha _{k}=\alpha _{k}/\beta ,k=k+1,返回步骤3.

(注:\alpha _{k} 不能取得太小,否则不能保证 d _{k} 是下降方向;\alpha _{k} 更不能取得太大,会影响收敛速度;根据经验,\alpha _{1} =0.01,\beta =10)

算法代码:

'''
最小二乘法(LM算法)
2023-11-13
'''
import numpy as np

# 定义目标函数
def fun(x, t, y):
    return x[0] * np.exp(-x[1] * t) - y

# 定义计算雅可比矩阵的函数
def jac(x, t):
    J = np.empty((len(t), 2))
    J[:, 0] = np.exp(-x[1] * t)
    J[:, 1] = -x[0] * t * np.exp(-x[1] * t)
    return J

# 定义最小二乘法函数
def least_squares(fun, x0, jac, t, y):
    max_iter = 100
    tol = 1e-6
    lam = 0.01
    x = x0.copy()

    for i in range(max_iter):
        r = fun(x, t, y)
        J = jac(x, t)
        JtJ = np.dot(J.T, J)
        g = np.dot(J.T, r)

        # 计算LM步长
        dx = np.linalg.solve(JtJ + lam * np.diag(np.diag(JtJ)), -g)

        x_new = x + dx
        r_new = fun(x_new, t, y)

        # 更新参数和LM参数
        if np.linalg.norm(r_new) < np.linalg.norm(r):
            x = x_new
            lam *= 0.1
        else:
            lam *= 10

        # 判断收敛条件
        if np.linalg.norm(dx) < tol:
            break

    return x

# 生成样本数据
t = np.linspace(0, 4, 50)
actual_params = np.array([2.0, 0.5])
y = fun(actual_params, t, 0) + 0.1 * np.random.randn(len(t))

# 定义初始参数值
x0 = np.array([1.0, 1.0])

# 使用最小二乘法拟合数据
res = least_squares(fun, x0, jac, t, y)

# 打印拟合结果
print("拟合参数:", res)

该代码所运算的结果为:

拟合参数: [1.98729463 0.49536682]

(行文中若有纰漏,希望大家指正)

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

背对人潮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值