『科学计算』最小二乘法

最小二乘法

线性最小二乘的基本公式

 

考虑超定方程组(超定指未知数小于方程个数):
其中m代表有m个等式,n代表有 n 个未知数
,m>n ;将其进行向量化后为:

  
显然该方程组一般而言没有解,所以为了选取最合适的
让该等式"尽量成立",引入残差平方和函数S
(在统计学中,残差平方和函数可以看成n倍的 均方误差MSE)
时,
取最小值,记作:
通过对
进行微分 求最值,可以得到:
如果矩阵
非奇异则
有唯一解   :

实质:m维空间点向n维空间的子空间的投影坐标,如下,向量空间A向C的投影就是点B。

拟合示意,最后得出来系数向量x,利用已知矩阵A乘上x,可以得出拟合后直线上的点集b向量,用于绘图即可:

作业一

已知A(3,1),C(1,3)求垂足B的坐标。

利用向量的垂直关系:

利用向量BC垂直于向量OA,且B在直线OA上两个已知条件,利用方程求解B点的坐标。

import numpy as np

def solve_point(a=[3,1], c=[1,3]):
    b=[]
    b.append((pow(a[0],2)*c[0] + a[0]*a[1]*c[1])/np.sum(np.square(a)))
    b.append((a[0]*a[1]*c[0] + pow(a[1],2)*c[1])/np.sum(np.square(a)))
    return b
solve_point()
[1.8, 0.59999999999999998]

利用最小二乘法:

注意如果不使用dot(矩阵乘法)的话,那么*乘法是numpy的广播乘法。

import numpy as np
import matplotlib.pyplot as plt

A = np.array([[3],[1]])
C = np.array([[1],[3]])

B = A.dot(np.linalg.inv(A.T.dot(A)).dot(A.T.dot(C)))
E = C - B

fig = plt.figure()
ax = fig.add_subplot(111)
ax.axis('equal')
ax.set_xlim(-1,5)

# 绘制直线OA
x = np.linspace(-1,5,6)
l = x * A
ax.plot(l[0,:],l[1,:])

# 绘制点
ax.plot(A[0],A[1],'ko')
ax.plot([C[0],B[0]],[C[1],B[1]],'r-o')
ax.plot([0,C[0]],[0,C[1]],'m-o')
ax.plot([0,E[0]],[0,E[1]],'k-o')

margin = 0.2
ax.text(A[0]+margin, A[1]+margin, "A",fontsize=20)
ax.text(C[0]+margin, C[1]+margin, "C",fontsize=20)
ax.text(B[0]+margin, B[1]+margin, "P",fontsize=20)
ax.text(E[0]+margin, E[1]+margin, "E",fontsize=20)

 

 

 作业二

最小二乘法拟合二维点

线性拟合:

import numpy as np
import matplotlib.pyplot as plt  
    
x = np.arange(-1,1,0.02)  
y = 2*np.sin(x*2.3)+0.5*x**3

y1 = y+0.5*(np.random.rand(len(x))-0.5)


##################################
# 写下你的Code
A = np.vstack((x, np.ones(len(x)))).T
print(A)
b = y.T
print(b)

def projection(A,b):
    ####
    # return A*inv(AT*A)*AT*b
    ####
    return A.dot(np.linalg.inv(A.T.dot(A)).dot(A.T.dot(b)))

yw = projection(A,b)
##################################

plt.plot(x,y,color='g',linestyle='-',marker='') 
plt.plot(x,y1,color='m',linestyle='',marker='o')

# 把拟合的曲线在这里画出来
plt.plot(x,yw,color='r',linestyle='',marker='.')

 

 扩展,多项式拟合:

import numpy as np  
import matplotlib.pyplot as plt  
    
x = np.arange(-1,1,0.02)  
y = ((x*x-1)**3+1)*(np.cos(x*2)+0.6*np.sin(x*1.3))

y1 = y+(np.random.rand(len(x))-0.5)

##################################
### write your code to gen A,b
m = []
for i in range(6):
    m.append(x**(i))

# A = 
# [[x1^6,x1^5...],
#  [x2^6,x2^5...],
#  ... ...]

A = np.array(m).T
b = y.T
##################################

def projection(A,b):
    ####
    # return A*inv(AT*A)*AT*b
    ####
    AA = A.T.dot(A)
    w=np.linalg.inv(AA).dot(A.T).dot(b)
    print(w)
    return A.dot(w)

yw = projection(A,b)
#yw.shape = (yw.shape[0],)

plt.plot(x,y,color='g',linestyle='-',marker='') 
plt.plot(x,y1,color='m',linestyle='',marker='o')
plt.plot(x,yw,color='r',linestyle='',marker='.')

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值