这次是用Qt实现 在线课程
GAMES102 几何建模与处理基础 ---- 刘利刚(我的男神2 , 授业解惑 放以前是要享万家香火的)
的作业1
课程链接:
http://staff.ustc.edu.cn/~lgliu/Courses/GAMES102_2020/default.html
作业内容:
Input: 已知平面内 n 个点 Pj(xj,yj),j=1,2,…,n。
output: 拟合这些点的函数
拟合方法:
(1)函数插值:基于幂基函数的多项式插值,基于gauss基函数的线性拟合,拉格朗日插值。特点:曲线经过所有输入点
(2)函数拟合:最小二乘法,岭回归。特点:曲线逼近所有输入点
以下部分内容引用他人优秀报告:
http://staff.ustc.edu.cn/~lgliu/Courses/GAMES102_2020/Homework/HW1-report.rar (可下载,含多人报告与不同平台的代码实现)
Tip1:详细代码请下载源代码看注释,博客以数学原理解析为主
Tip2: 用外库Eigen来解矩阵
Tip3: 本节作业分为两节,(上)写多项式插值,(下)写多项式拟合,(下)链接
程序源代码:https://pan.baidu.com/s/1xcMtDS31XkFa9wL28AUv7g 提取码:cqli
编译环境:Qt5.9.4, Eigen
编译器:Desktop Qt5.9.4 MSVC2017 64bit
IDE:QtCreator
一,程序简介
在白色画布上,用鼠标左键单击采样输入点,选择拟合选项后,点击“Fitting”按钮拟合输入点。点击“Clear”按钮对画布进行清除。
二,数学推导
数值分析(第5版)-李庆杨 p22页,对插值问题的定义就很nice。我自己有一个通俗的理解,如果在[a, b]内曲线连续可导,则这个曲线可以由不用的基函数进行拟合,这个基函数空间可以是幂函数,RBF函数,三角函数等等。
2.1多项式插值的定义
2.1.1 幂基函数
课本的下一页,给出了多项式插值的定义,换成程序语言的介绍,只要输入(n+1)个x值不同的点,就能通过幂基函数的拟合,得到拟合曲线。这里是因为 y = f(x) 如果存在两个点的x值相同,但y值不同,矩阵就会产生歧义。所以要求x值不同。对x值的限定这个问题可以通过后续的曲线参数化解决,令x = f(t), y = p(t),将x与y互相孤立即可。
在代码里实际求解时,这里引用优秀报告里常同学的解释:
x0,x1,,,xn是我们输入的n+1个点的x坐标值,y0,,,,yn是对应的y坐标值,因为B是一个范德蒙式,行列式不等于0,可逆。所以直接求解
,
就可以得到多项式函数,接着将x=0到窗口的宽度400代入函数,算出这条曲线的所有点,连线即可。
我们可以明显看出,当输入点n变多时,会导致多项式曲线阶数过高,带来不稳定的震荡。这是因为多项式插值问题式病态的,范德蒙矩阵的条件数随着输入点数n呈指数级增长,矩阵条件数过大,导致矩阵容易病态,就容易过拟合,出现龙格现象,即在两端处波动极大,产生明显的震荡。
2.1.2 Gauss基函数
高斯函数:
几何意义上:
μ: 控制位置
σ:控制支集宽度
这里还是用常同学的解释,我们将简单的幂基函数换为Gauss基函数,通过调整σ的数值,得到的不同拟合曲线。
本质上,径向基函数插值函数的 f(x),是在每一个输入点上,都放置一个bi*gi(x),并将所有输入点上的bi*gi(x)加起来进行拟合。如下图,当σ=5,支集宽度过小时,就可以明显看出,f(x)本质是在每个输入点上都放了一个gauss基函数,然后将所有输入点上的函数加起来。
通过Input输入点,G,Y已知,且G满秩可逆,所以
,
将b的各项带入f(x),则曲线已知,画出其余曲线各点,连线即可。
(1)σ = 50
(2)σ = 20