几何建模与处理-数据拟合

625 阅读5分钟

图形学有"建模"、"仿真"、"渲染"三大模块,各个模块之间又有很紧密的联系。

图形学三大模块

从这篇文章开始,整理几何建模与处理的基础知识,内容/代码主要参考中科大刘利刚老师的课程《games102-几何建模与处理基础》

数据拟合方法

根据Weierstrass逼近定理:

  • 定理1:闭区间上的连续函数可用多项式级数一致逼近
  • 定理2:闭区间上周期为2π的连续函数可用三角函数级数一致逼近

从多项式入手,讲4种代表性的拟合方法。先介绍原理,后提供代码及工程说明。

多项式插值(lagrange插值)

过两点确定一条直线 y = ax + b,解方程可以得到未知数 a、b的值。然后可以得到直线上其他点的坐标,这就是最简单的插值,此时多项式的次数为1。

如果多个点不在一条直线上呢?可以回忆下高数里的泰勒展开式,多项式可以逼近任意连续的曲线

泰勒展开式:f(x)=i=0n1αiBi(x)f(x)=\sum_{i=0}^{n-1}\alpha_i B_i(x) 插值 {Pj}\{P_j\},其中 Bi(x)=xiB_i(x)=x^i

如果点比较多,则x项比较多,解方程不太容易。用lagrange插值法比较容易,理解也相对直观。

lagrange插值法:

polygon 插值

限于篇幅,不做展开。lagrange插值法原理参考:

gauss插值

高斯插值本质上,就是在多项式插值的基础上,将基函数从多项式{1,x1,x2,x3,...,xn}\{1, x^1, x^2, x^3, ..., x^n\},改成高斯函数

使用 Gauss 基函数的线性组合 f(x)=b0+i=1nbigi(x)f(x)=b_0 + \sum_{i=1}^{n}b_i g_i(x) 插值 {Pj}\{P_j\},其中

g(x)=exp((xμ)22σ2),μ=x1,x2,,xng(x)=\exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right),\mu=x_1,x_2,\dots,x_n

即对称轴在插值点上,i=1,,ni=1,\dots,n,缺省设 σ=1\sigma =1

不要被这个高斯基函数吓到了,代入已知的点,g(x)的值可以明确的计算出来,最后变成解多元方程,解出每一个bib_i的值 {b0,b1,b2,bn}\{b_0, b_1, b_2 \dots, b_n\}

gauss 插值

观察上图示例,高斯插值更侧重突出插入点,通过调σ\sigma值,可以很好的控制曲线变化的幅度。

注意: 实际上方程组还多了一个b0b_0是未知的,b0b_0有两种方法确定,

  • 通过人为的增加一个点,比如取最后两个点的中间值 f(xn+xn12)=yn+yn12f \left(\frac{x_n + x_{n-1}}{2} \right) = \frac{y_n + y_{n-1}}{2}

  • 直接取所有插值点y坐标的平均值

下面计算gauss插值的代码中,我有点偷懒,直接去掉了b0b_0项,有兴趣,你可以补上b0b_0

高斯函数拟合可以参考: 拟合与高斯分布

无论多项式插值,还是高斯插值,都是选一组规律的函数来拟合插值的点,通过解方程,得到一个"漂亮"的拟合函数曲线,当然还有很多其他的插值基函数,不过原理都类似。

多项式拟合

如果多项式的次数太大,方程解起来很花时间,那怎么办呢?可以用低阶的多项式来近似拟合,不要求拟合出来的曲线能刚好穿过每一个点,只要路径近似就能满足要求。

具体怎么操作呢?比如有4个点,但我只想用基函数{1,x1,x2}\{1, x_1, x_2\}来拟合,4个点对应4个方程,但是只有三个未知数{b0,b1,b2}\{b_0, b_1, b_2\},就造成过拟合,方程是无解的。

使得当条件mini=0n(yiαixi)2min\sum_{i=0}^{n} (y_i - \alpha_i x^i)^2成立时,对应的α\alpha值,α=[α0,α1,,αn]\alpha = [\alpha_0, \alpha_1, \dots, \alpha_n]

可以用最小二乘法来求一个近似的解,如果你还记得线性代数,或者学过机器学习,很好理解。

下面附一个讲的浅显易懂的文章,从偏导和几何的角度分别给出了解释: 最小二乘法

polygon 拟合

注意:如果多项式次数比较高,或者基函数选择的比较复杂,用最小二乘法可能无解,在机器学习领域,用梯度下降的方法来求解(模型训练)。

岭回归拟合

岭回归是概率统计的概念,在机器学习领域称为"正则化"。

在多项式拟合的基础上,增加了多项式的权重,这个解释起来有点繁琐,简言之,让曲线泛化的更好,我希望曲线不要太贴近插入的点,因为有可能某一个点是"噪点",把整个曲线带的很陡峭,增加"正则项",使得曲线拟合的更稳定。

岭回归

工程介绍

代码基于'陈昱文-作业'修改完善,IDE使用CLion

工程目录:

工程界面

  • CPM.cmake cmake拓展,便于第三方库版本管理和集成
  • glad GLFW 渲染接口层
  • imgui 轻量的GUI框架,很方便的创建操作面板、按钮等交互空间
  • eigen,线性代数计算库(和GLM类似,GLM主要和opengl配合使用,方便计算相机矩阵)
  • MathUtil类,实现了上述几种拟合算法
  • 主要调用逻辑在main.cpp中

简单的配置,就能实现一个轻便的交互界面,麻雀虽小五脏俱全。上面依赖的常用库真要深入进去吃透了,也非常强大。

读者朋友可以下载完整代码编译运行,参考原理介绍,梳理整个流程。