移动最小二乘法MLS(Moving Lest Squares)简要介绍

移动最小二乘法MLS(Moving Lest Squares):附PYTHON代码

1. Overview

移动最小二乘法(MLS, Moving Least Squares)是建立大量离散数据拟合曲线的理想方法。当大量离散数据的分布较为杂乱时, 使用传统的最小二乘法,往往需要对数据进行分段拟合,此外还要避免相邻分段上的拟合曲线不连续不平滑的问题。而MLS法在处理相同问题时则不需要上述这些繁琐的步骤,简单易于实现。

在MLS法中,需要在一组不同位置的节点(node)附近建立拟合曲线,每个节点都有自己的一组系数 ( a j ( x n o d e ) a_j(x_{node}) aj(xnode)) 用于定义该位置附近拟合曲线的形态。因此,在计算某个节点附近的拟合曲线时,只需要计算该点的该组系数值( a j a_j aj)即可。

此外,每个节点的系数( a j a_j aj)取值只考虑其临近采样点,且距离节点越近的采样点贡献越大,对于未置较远的点则不予考虑。

2. 拟合函数

相比于传统的最下二乘法,MLS法中的拟合函数不是一个多项式,而是一组系数向量函数 a j ( x ) a_j(x) aj(x)和基函数 p j ( x ) p_j(x) pj(x),其中 x x x为空间坐标。

某个节点node附近的拟合函数即为 u n o d e ( x ) u_{node}(x) unode(x),具体定义为如下公式。
u n o d e ( x ) = ∑ j = 1 m a j ( x n o d e ) ∗ p j ( x ) u_{node}(x)=\sum_{j=1}^ma_j(x_{node})*p_j(x) unode(x)=j=1maj(xnode)pj(x)

其中, x n o d e x_{node} xnode为节点的空间坐标, x x x为节点node附近的某一个位置坐标, a j a_j aj即为用于定义节点node附近拟合曲线的一组系数, p j ( x ) p_j(x) pj(x)则是一组基函数,其常用形式如下:

空间维度一阶形式二阶形式
1维: x = ( x ) \bm{x}=(x) x=(x) p 1 = 1 , p 2 = x p_1=1, p_2=x p1=1,p2=x p 1 = 1 , p 2 = x , p 3 = x 2 p_1=1, p_2=x, p_3=x^2 p1=1,p2=x,p3=x2
2维: x = ( x , y ) \bm{x}=(x,y) x=(x,y) p 1 = 1 , p 2 = x , p 3 = y p_1=1, p_2=x, p_3=y p1=1,p2=x,p3=y p 1 = 1 , p 2 = x , p 3 = y , p 4 = x y , p 5 = x 2 , p 6 = y 2 p_1=1, p_2=x, p_3=y, \\p_4=xy, p_5=x^2, p_6=y^2 p1=1,p2=x,p3=y,p4=xy,p5=x2,p6=y2
3维: x = ( x , y , z ) \bm{x}=(x,y,z) x=(x,y,z) p 1 = 1 , p 2 = x , p 3 = y , p 4 = z p_1=1, p_2=x, p_3=y, p_4=z p1=1,p2=x,p3=y,p4=z p 1 = 1 , p 2 = x , p 3 = y , p 4 = z , p 5 = x y , p 6 = x z , p 7 = y z , p 8 = x 2 , p 9 = y 2 , p 10 = y 2 p_1=1, p_2=x, p_3=y, p_4=z,\\p_5=xy, p_6=xz, p_7=yz,\\ p_8=x^2, p_9=y^2, p_{10}=y^2 p1=1,p2=x,p3=y,p4=z,p5=xy,p6=xz,p7=yz,p8=x2,p9=y2,p10=y2

MLS法中,需要通过调整系数 a a a,使得节点node附近采样点取值与拟合函数在采样点取值之间差的加权平方和最小,由此可建立最优化模型J。
J = ∑ p = 1 n w ( x n o d e − x p ) [ u ( x n o d e ) − u p ] 2 = ∑ p = 1 n w ( x n o d e − x p ) [ ∑ j = 1 m a j ( x n o d e ) ∗ p j ( x ) − u p ] 2 = ∑ p = 1 n w ( x n o d e − x p ) [ ∑ j = 1 m a j n o d e ∗ p j ( x ) − u p ] 2 J=\sum_{p=1}^n w(x_{node}-x_p)[u(x_{node})-u_p]^2\\=\sum_{p=1}^n w(x_{node}-x_p)[\sum_{j=1}^ma_j(x_{node})*p_j(x)-u_p]^2\\=\sum_{p=1}^n w(x_{node}-x_p) [\sum_{j=1}^ma_j^{node}*p_j(x)-u_p]^2 J=p=1nw(xnodexp)[u(xnode)up]2=p=1nw(xnodexp)[j=1maj(xnode)pj(x)up]2=p=1nw(xnodexp)[j=1majnodepj(x)up]2
其中, x n o d e x_{node} xnode为节点node的空间位置, p p p为采样点, x p x_p xp为采样点p的空间位置, u p u_p up是采样点p的取值,此处 a j ( x n o d e ) = a j n o d e a_j(x_{node})=a_j^{node} aj(xnode)=ajnode
在这里插入图片描述

上式中的 w w w为权函数,该函数保证距离node越近的采样点,对于函数 J J J的贡献越大,而对于距离node较远的位置的采样点,则不会对J产生影响。函数 w w w的常用形式如下(三次样条曲线)。

权重函数
其中,当采样点p与节点node的距离大于一定值时(此处为2),权重函数 w w w的取值为零。(上图中 ∣ x ∣ |x| x为矢量 x x x的模)。当然,该函数的邻域阈值可根据需要设定为合适的值。

最终求解出在问题域上全部节点的系数,即可得到全域上的拟合曲线。

3. 系数计算

如上文所述,每个节点都有自己的一组系数 ( a j ( x n o d e ) a_j(x_{node}) aj(xnode)) 用于定义该位置附近拟合曲线的形态,本节将叙述该系数的具体求解方法。

我们已经获得了参数为系数 a j n o d e a_j^{node} ajnode的最优化模型 J J J,当 J J J的取值最小时,则可获得节点node附近的拟合曲线 u n o d e ( x ) u_{node}(x) unode(x)

求解最优化模型最直接的方式,即是对模型求导,因此我们可得到如下方程。

∂ J ∂ a i n o d e = 2 ∑ p = 1 n w ( x n o d e − x p ) [ ∑ j = 1 m a j n o d e ∗ p j ( x ) − u p ] p i ( x ) \frac{\partial{J}}{\partial{a_i^{node}}}=2\sum_{p=1}^n w(x_{node}-x_p) [\sum_{j=1}^ma_j^{node}*p_j(x)-u_p]p_i(x) ainodeJ=2p=1nw(xnodexp)[j=1majnodepj(x)up]pi(x)
当上式得零时, J J J取得最小值,因此可得:

∑ p = 1 n w ( x n o d e − x p ) [ ∑ j = 1 m a j n o d e ∗ p j ( x ) − u p ] p i ( x ) = 0 \sum_{p=1}^n w(x_{node}-x_p) [\sum_{j=1}^ma_j^{node}*p_j(x)-u_p]p_i(x)=0 p=1nw(xnodexp)[j=1majnodepj(x)up]pi(x)=0

∑ p = 1 n w ( x n o d e − x p ) ∑ j = 1 m a j n o d e ∗ p j ( x ) = ∑ p = 1 n w ( x n o d e − x p ) u p ∗ p i ( x ) \sum_{p=1}^n w(x_{node}-x_p) \sum_{j=1}^ma_j^{node}*p_j(x)=\sum_{p=1}^n w(x_{node}-x_p) u_p*p_i(x) p=1nw(xnodexp)j=1majnodepj(x)=p=1nw(xnodexp)uppi(x)

我们引入下述记号以简化表达(内积):
( p i , p j ) = ∑ p = 1 n w ( x n o d e − x p ) ∗ p i ( x ) ∗ p j ( x ) ( u p , p j ) = ∑ p = 1 n w ( x n o d e − x p ) ∗ u p ∗ p j ( x ) (p_i,p_j)=\sum_{p=1}^n w(x_{node}-x_p) *p_i(x)*p_j(x)\\(u_p,p_j)=\sum_{p=1}^n w(x_{node}-x_p)*u_p*p_j(x) (pi,pj)=p=1nw(xnodexp)pi(x)pj(x)(up,pj)=p=1nw(xnodexp)uppj(x)

因此,最终我们可将 ∂ J ∂ a i n o d e = 0 \frac{\partial{J}}{\partial{a_i^{node}}}=0 ainodeJ=0整理成如下的线性方程组。该线性方程组也被称为法方程。
[ ( p 1 , p 1 ) . . . ( p 1 , p j ) . . . ( p 1 , p m ) . . . ( p i , p 1 ) . . . ( p i , p j ) . . . ( p i , p m ) . . . ( p m , p 1 ) . . . ( p m , p j ) . . . ( p m , p m ) ] ∗ [ a 1 n o d e . . . a j n o d e . . . a m n o d e ] = [ ( u p , p 1 ) . . . ( u p , p j ) . . . ( u p , p m ) ] \left[ \begin{array}{ccc} (p_1,p_1) &... & (p_1,p_j) &... &(p_1,p_m)\\ ...&&&&\\ (p_i,p_1)& ...& (p_i,p_j)& ...& (p_i,p_m)\\ ...&&&&\\ (p_m,p_1) &...&(p_m,p_j)& ... & (p_m,p_m) \end{array} \right ]*\left[ \begin{array}{ccc} a_1^{node}\\ ...\\ a_j^{node}\\ ...\\ a_m^{node}\\ \end{array} \right ]=\left[ \begin{array}{ccc} (u_p,p_1)\\ ...\\ (u_p,p_j)\\ ...\\ (u_p,p_m)\\ \end{array} \right ] (p1,p1)...(pi,p1)...(pm,p1).........(p1,pj)(pi,pj)(pm,pj).........(p1,pm)(pi,pm)(pm,pm)a1node...ajnode...amnode=(up,p1)...(up,pj)...(up,pm)
该线性方程组可写成矩阵形式 : M a ⃗ = b ⃗ M \vec a=\vec b Ma =b ,其中 M M M为由基函数构成的系数矩阵, a ⃗ \vec a a 是未知数向量,也就是我们要求节点node上的那一组系数。因此未知数向量 a ⃗ \vec a a 也可表示为: a ⃗ = M − 1 b ⃗ \vec a =M^{-1}\vec b a =M1b

解出上述线性方程组,即可得到在节点node上的改组系数 a j n o d e a_j^{node} ajnode。通过系数 a j n o d e a_j^{node} ajnode与基向量 p j ( x ) p_j(x) pj(x)就可建立出节点node附近的拟合函数。

进一步的,我们可以将任意位置上的拟合函数写成如下形式(即节点node的位置可为任意点 x \bm{x} x):

u ( x ) = ∑ j = 1 m a j ( x ) ∗ p j ( x ) = P ⋅ a ⃗ u(\bm{x})=\sum_{j=1}^ma_j(\bm{x})*p_j(\bm{x})= P \cdot \vec a u(x)=j=1maj(x)pj(x)=Pa
a ⃗ = M − 1 ⋅ b ⃗ \vec a =M^{-1}\cdot \vec b a =M1b 带入后,可得:
u ( x ) = P ⋅ a ⃗ = P ⋅ M − 1 ⋅ b ⃗ u(x)=P \cdot \vec a = P \cdot M^{-1}\cdot \vec b u(x)=Pa =PM1b
其中:
M = [ ( p 1 , p 1 ) . . . ( p 1 , p j ) . . . ( p 1 , p m ) . . . ( p i , p 1 ) . . . ( p i , p j ) . . . ( p i , p m ) . . . ( p m , p 1 ) . . . ( p m , p j ) . . . ( p m , p m ) ] M= \left[ \begin{array}{ccc} (p_1,p_1) &... & (p_1,p_j) &... &(p_1,p_m)\\ ...&&&&\\ (p_i,p_1)& ...& (p_i,p_j)& ...& (p_i,p_m)\\ ...&&&&\\ (p_m,p_1) &...&(p_m,p_j)& ... & (p_m,p_m) \end{array} \right ] M=(p1,p1)...(pi,p1)...(pm,p1).........(p1,pj)(pi,pj)(pm,pj).........(p1,pm)(pi,pm)(pm,pm)

b = [ ( u p , p 1 ) . . . ( u p , p j ) . . . ( u p , p m ) ] b= \left[ \begin{array}{ccc} (u_p,p_1)\\ ...\\ (u_p,p_j)\\ ...\\ (u_p,p_m)\\ \end{array} \right ] b=(up,p1)...(up,pj)...(up,pm)

因此我们可以在任意点 x \bm{x} x上计算出拟合函数及其取值,并且空间上相邻的两点的取值是很平滑的。

4. 注意

①本文中的 p i ( x ) p_i(x) pi(x)为基向量,而下标 p p p则指的是采样点 p p p,如 x p x_p xp
②本文中,采样点的个数表示为 n n n,基向量的个数为 m m m;
③网格node上的一组系数表示为 a i n o d e a_i^{node} ainode, 其中 i = 1 , . . . m i=1,...m i=1,...m;
④每个采样点上携带有两部分信息,一部分是该采样点的空间位置 x p x_p xp,另一部分是采样点取值 u p u_p up,这两部分信息都是已知的。

5. 扩展

MLS法其实是一种广义的最小二乘法方法。MLS法的核心优化模型J:
J = ∑ p = 1 n w [ u ( x ) − u p ] 2 = ∑ p = 1 n w ( x − x p ) [ ∑ j = 1 m a j ( x ) ∗ p j ( x ) − u p ] 2 J=\sum_{p=1}^n w[u(\bm{x})-u_p]^2\\ =\sum_{p=1}^n w(\bm{x} - \bm{x}_p)[\sum_{j=1}^ma_j(\bm{x})*p_j(\bm{x})-u_p]^2\\ J=p=1nw[u(x)up]2=p=1nw(xxp)[j=1maj(x)pj(x)up]2
① 当权函数 w = 1 w=1 w=1 时(如下图曲线),则上述MLS方法退化成标准的标准的最小二乘法。

在这里插入图片描述
② 当权函数 w = w ( x ) w=w(\bm{x}) w=w(x) 为高斯函数或样条曲线时(如下图曲线),则上述MLS方法退化成固定点最小二乘法(FLS, fixed least-squares)
在这里插入图片描述
③ 在MLS法中权函数为: w = w p ( x ) = w ( x − x p ) w=w_p(\bm{x})=w(\bm{x} - \bm{x}_p) w=wp(x)=w(xxp),一般也为高斯函数或类似样条函数,且以 x \bm{x} x点为中心点取最大值,在 x \bm{x} x其相邻区域上取值逐渐减小。

④ 当权函数为 w = w ( x ) w=w(\bm{x}) w=w(x)的曲线为如下形式时,则上述MLS法退化为多固定点最小二乘法(MFLS,Multiple fixed least-squares)
在这里插入图片描述
另附我自己写的代码,若有bug请回复。

import numpy as np  
import random
from matplotlib import pyplot as plt

Consistency = 3  #阶数
d = 0.9	#紧支域半径
dotNumber = 36	#散点数量
dotDinstance = 0.05	#散点间距

test = 0	# 0 为曲线,1 为直线

x = []
v = []
Vp = []
p = np.zeros((dotNumber, Consistency))
M = []


def w(xi,xj,d):
    s = abs(xi-xj)/d
    if(s <= 0.5):
        return (2/3)-4*s+4*s**2+4*s**3
    elif(s<=1):
        return (4/3)-4*s+4*s**2-(4/3)*s**3
    else:
        return 0

def b_compute(i, x, v, d):
    b = []
    for c in range(Consistency):
        t = 0
        for j in range(dotNumber):
            # if abs(x[i] - x[j]) < d:
                t +=  p[j][c] * w(x[i], x[j], d) * v[j]
        b.append(float(t))
    return b
        # for j in range(0, Consistency):
        #     w()


def A_compute(i, x, d):
    A = []
    for ci in range(Consistency):
        vec = []
        for cj in range(Consistency):
            t = 0
            for j in range(dotNumber):
                t +=  w(x[i], x[j], d) * p[j][cj] * p[j][ci]
            vec.append(float(t))
        A.append(vec)
    return A



def polySet(p,x):
    for i in range(dotNumber):
        for j in range(0, Consistency):
            p[i][j] = x[i]**(j)


def Vcontruct(a,x,i):
    value = 0
    for c in range(len(a)):
        value +=  a[c] * x[i]** c
    return value

def main():
    x = np.arange(-0.5*dotNumber*dotDinstance, 0.5*dotNumber*dotDinstance, dotDinstance)

    for i in range(0, dotNumber):
        if test == 0:
            v.append(i + random.randint(-50,50)/10)
            # v.append(random.randint(-50, 50) / 10)
        else:
            v.append(i + 0 / 10)

    polySet(p,x)

    for i in range(dotNumber):
        b = b_compute(i, x, v, d)

        A = A_compute(i, x, d)
        a = np.linalg.solve(A, b)
        Vp.append(Vcontruct(a, x, i))
        # V.append(a[0]+a[1]*x[i])

    plt.title("MLS")
    plt.xlabel("x")
    plt.ylabel("y")
    plt.scatter(x,v,color = "green", s= 10)
    plt.plot(x, Vp)
    plt.show()

if __name__ =='__main__':
    main()








  • 50
    点赞
  • 176
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值