利用matlab实现非线性拟合[三维、高维、参数方程]
一般而言,通过已有的数据点去推导其它数据点,常见的方法有插值和拟合。插值适用性较广,尤其是线性插值或样条插值已被广泛的应用。但是通过已知的函数去拟合数据,是连接理论与实验重要的桥梁,这一点是插值无法替代的。
日常学习工作中,经常会遇到下面这种问题:想要用某个具体函数去拟合自己的数据,明明知道这个函数的具体形式,却不知道其中的参数怎么选取。本文就简单介绍一下matlab环境下,如何进行非线性拟合。
多项式拟合就是利用下面形式的方程去拟合数据:
y = a + b x + c x 2 + d x 3 + ⋯ y=a+bx+cx^2+dx^3+\cdots y=a+bx+cx2+dx3+⋯
matlab中可以用 polyfit() 函数进行多项式拟合。下面举一个小例子:
对于已有的数据点,我们采用4阶多项式拟合。其中已知函数的的表达式为
y = 0.03 x^4 - 0.5 x^3 + 2 x^2 - 4
在此基础上添加了一些噪声点。拟合曲线依然采用 4 阶进行拟合,结果如下。
可以看到拟合曲线与理论曲线基本一致,说明这种方法能够较好的拟合出原始数据的趋势
。
对于多项式拟合,不是阶数越多越好。
比如还是这个上面这个例子,阶数越多,曲线越能够穿过每一个点,但是曲线的形状与理论曲线偏离越大。所以选择最适合的才是最好的。
非
线性拟合前面介绍了线性的拟合方法。如果一个非线性方程,可以化为上面线性方程中公式中给出的样子,那么我们也可以套用线性的方法去求解。
比如下面的方程:
y = a ∗ e x p ( − b x ) y=a*exp(-bx) y=a∗exp(−bx)
经过取对数变换,可以变为下面等效的线性形式:
l g ( y ) = l g ( a ) + b ∗ ( − x ) lg(y)=lg(a)+b*(-x) lg(y)=lg(a)+b∗(−x)
这样求出来之后,再反变换回去,就可以得到原方程的系数了。
matlab 自带了一个 Curve Fitting App,它在 matlab 集成的 App 里面。
界面里常用的拟合方式都有,而且直接展示拟合效果,非常方便。非常适合鼠标直接拖拖拽拽点点点的操作方式。
matlab中,fit()函数是一个比较通用的用于函数拟合的函数。
对于非线性拟合,可以使用 fit() 函数中的 Nonlinear Least Squares 方法。其大概原理为,首先确定一个初始的点,计算该点的雅可比矩阵
J,来近似线性化的判断该点周围的趋势,并将这个点向更小的方向移动。
相比于前面的fit()函数,nlinfit()函数是matlab专门的非线性拟合函数。对于非稳健估计,采用的是Levenberg-Marquardt(LM)方法,也叫阻尼最小二乘法。
对于稳健估计,采用的是Iteratively Reweighted Least Squares方法,也就是在Least Squares基础上,对每一个拟合点的权重进行调整的一种方法。这两者方法也都是基于雅克比矩阵的方法。
lsqnonlin() 也是 matlab 中自带的一个非线性拟合函数。它给出了两种计算非线性拟合的方法,一种是比较经典之前介绍过的 LM 方法,一种是信赖域方法。
信赖域法(trust region reflective)是通过Hessian 矩阵,逐步试探邻域内的最小化,来求解问题的。相比较之前的那些雅克比相关的方法,信赖域法会占用更多内存和速度,所以适用于中小规模的矩阵。
lsqcurvefit()函数和lsqnonlin()内容上相似,只是引用格式上有所不同。
这也是一个求解非线性方程的函数,可以求解方程组或者矩阵形式,功能非常强大。默认的算法为trust-region-dogleg,俗称狗腿法,属于信赖域法。这里用到的功能比较基础,所以也不过多介绍了。
说了那么多,发现逐渐从如何非线性拟合
,陷入到了最优化
的深坑里。
而且前面的那么多方法,很多都解决不了陷入到局部最优解的问题。实际上,这种问题如果进入了最优化领域,很多智能算法也可以被考虑进来。所以我也把粒子群PSO算法
加入到了里面,尝试将结果收敛到全局最优解。
[1] https://blog.csdn.net/weixin_42943114/article/details/116803379