python用最小二乘法实现平面拟合

文章目录

数学原理

平面方程可写为

A x + B y + C z + D = 0 Ax+By+Cz+D=0 Ax+By+Cz+D=0

假设 C C C不为0,则上式可以改写为

z = a x + b y + d z=ax+by+d z=ax+by+d

则现有一组点 { p i } \{p_i\} {pi},则根据 x i , y i x_i,y_i xi,yi以及平面方程,可以得到其对应的 z ^ i \hat z_i z^i

z ^ i = a x i + b y i + d \hat z_i=ax_i+by_i+d z^i=axi+byi+d

从而平面拟合就转换为了最小二乘问题

arg min ⁡ ∑ ∣ z i − z ^ i ∣ \argmin \sum \vert z_i-\hat z_i\vert argmin∑∣zi−z^i∣

将其转换为矩阵形式,记

A = x 1 y 1 1 x 2 y 2 1 ⋮ ⋮ x n y n 1 , x = a b d , b = z 1 z 2 ⋮ z n A=\begin{bmatrix} x_1&y_1&1\\x_2&y_2&1\\\vdots&\vdots\\x_n&y_n&1 \end{bmatrix}, x=\begin{bmatrix}a\\b\\d\end{bmatrix}, b=\begin{bmatrix}z_1\\z_2\\\vdots\\z_n\end{bmatrix} A= x1x2⋮xny1y2⋮yn111 ,x= abd ,b= z1z2⋮zn

则拟合方程变为

A x = b Ax=b Ax=b

相应地 x x x可写为

x = ( A T A ) − 1 A T b x=(A^TA)^{-1}A^Tb x=(ATA)−1ATb

最小二乘法的原理可见:python实现最小二乘法

代码实现

其代码实现如下

python 复制代码
import numpy as np
def planefit(points):
    xs, ys, zs = list(zip(*points))
    A = np.vstack([xs,ys,np.ones_like(xs)]).T
    b = np.reshape(zs, [-1, 1])
    abd = np.linalg.inv(A.T @ A) @ A.T @ b
    return abd.reshape(-1)

其中输入参数points为一组点。第一步将这些点进行坐标拆分,得到一一对应的xs, ys, zs。然后通过这些点,构造矩阵A和向量b,最后输出 ( A T A ) − 1 A T b (A^TA)^{-1}A^Tb (ATA)−1ATb。

测试

首先做一个初始化平面的函数,其功能是随机生成一组在平面中的点,并且为其添加一些噪声。

python 复制代码
# 初始化平面
def initPlane(a, b, d, N, err=0.1):
    xs,ys = np.random.rand(2, N)
    zs = a*xs + b*ys + d + np.random.rand(N)*err
    return list(zip(xs, ys, zs))

然后用planefit函数对这些点进行拟合,通过对比二者之间的差异,来证实算法的有效性

python 复制代码
import matplotlib.pyplot as plt

pts = initPlane(2,3,4,100,1)
a,b,d = planefit(pts)

xs, ys = np.indices([100,100])/100
zs = a*xs + b*ys + d

ax = plt.subplot(projection='3d')
ax.plot_surface(xs, ys, zs, cmap='jet')
ax.scatter(*np.array(pts).T, marker='*')
plt.show()

随着加入的噪声逐渐变大,拟合误差也越来越大

python 复制代码
errs = [0.01, 0.1, 0.2, 0.5, 1, 3, 5]
fits = []
for err in errs:
    pts = initPlane(2,3,4,100,1)
    a,b,d = planefit(pts)
    fits.append([abs(a-2),abs(b-3),abs(d-4)])

import pprint
pprint.pprint(fits)

\[0.09377971025135245, 0.023025216275622373, 0.4933931906466551,

0.044310965250572654, 0.05681830483294226, 0.47952260969370997,

0.051813469166934745, 0.017914573861143257, 0.47553046120193176,

0.08578595894551588, 0.0464898508775029, 0.42791269232718054,

0.011569662177250528, 0.15976404558136714, 0.4886516489062753,

0.006829071411009302, 0.04832062421804073, 0.5193494695593301,

0.1651263679674586, 0.0736367910618192, 0.44103226768552073\]


相关推荐
星云穿梭11 小时前
用Python写一个带图形界面的学生管理系统——完整教程
python
金銀銅鐵11 小时前
用 Pygame 实现 15 puzzle
python·数学·游戏
黄忠17 小时前
大模型之LangGraph技术体系
python·llm
hboot1 天前
AI工程师第二课 - 数据处理
人工智能·python·数据分析
用户8356290780511 天前
使用 Python 自动化 PowerPoint 形状布局与格式设置
后端·python
用户8356290780512 天前
用 Python 自动化 PowerPoint 演讲者备注添加
后端·python
黄忠2 天前
01-系统架构设计-LangGraph状态机与多源异构RAG
python
zzzzzz3102 天前
假如我是掘金管理员,我先给评论区装个'代码审查'系统
python·程序员·机器人
砍材农夫2 天前
python环境|conda安装和使用(2)
后端·python
程序员龙叔2 天前
编写高质量 Skill 系列 -- 如何设计需求分析与用例生成的 SKILL
自动化测试·软件测试·python·软件测试工程师·接口测试·性能测试·skill·ai测试