继续说多项式的数值及拟合,这次主要讨论关于多项式拟合的函数fit。定义如下:
classmethod polynomial.polynomial.Polynomial.fit
(x, y, deg, domain=None, rcond=None, full=False, w=None, window=None, symbol='x')
Polynomial类下面有一个函数fit,官方是这么介绍的:
Least squares fit to data.
Return a series instance that is the least squares fit to the data y sampled at x. The domain of the returned instance can be specified and this will often result in a superior fit with less chance of ill conditioning.
简单来说,就是通过最小二乘拟合曲线,还是以前面的函数为例:
测试该函数,我们可以先通过原函数,生成系列的对应点,然后利用这些点进行数据的拟合:
import numpy as np
import matplotlib.pyplot as plt
from numpy.polynomial import Polynomial as P
np.polynomial.set_default_printstyle("unicode")
a=P([1,-2,0,3])
x=np.linspace(-2,2,100)
y0=a(x)
#通过[x,y0]点对,拟合多项式b
b=P.fit(x,y0,3,domain=a.domain)
print(b) # 1.0 - 2.0·x + (9.3447833e-15)·x² + 3.0·x³
# 绘制拟合多项式的图形
y1=b(x)
plt.plot(x,y0,'r')
plt.plot(x,y1,'b--')
plt.grid()
plt.show()
运行结果如下:
可以看到,两个图形几乎完全重叠,但是,得到的多项式b的表达式为:
抛开x的平方项,得到的是:
和原来的多项式相同。
注意,在拟合的时候,除了需要提供拟合的度,该值的取值要根据数据的特性选择合适的值,例如如果将度指定为2,其结果是线性最小二乘法:
还要指定其域(domain),该值通常应该设定为[-1,1]。
以上用了三个篇幅,算是将现有的轮子做了一个概述,通常情况下我们是可以直接拿来用的,不过在使用之前,一定要知道其使用范围,不能机械化的套用就完事了。
此外,这个函数在一些场合可能也满足不了我们的需求。首先,一个良好的拟合,需要依据数据的特点选择合适的拟合函数,多项式拟合并不一定是最好的选择,可能还有其他的函数关系;其次,即使是多项式拟合,也不是度越高越好,否则,容易产生所谓的过拟合现象,例如著名的龙格现象(Runge's Phenomenon):
import numpy as np
import matplotlib.pyplot as plt
from numpy.polynomial import Polynomial as P
np.polynomial.set_default_printstyle("unicode")
def f(x):
return 1/(1+x*x)
x=np.linspace(-10,10,100)
fh=np.vectorize(f)
y=fh(x)
g=P.fit(x,y,5,domain=[-1,1])
y1=g(x)
h=P.fit(x,y,10,domain=[-1,1])
y2=h(x)
fig0,=plt.plot(x,y,'r')
fig1,=plt.plot(x,y1,'g--')
fig2,=plt.plot(x,y2,'b--')
plt.title("Runge's Phenomenon")
plt.legend([fig0,fig1,fig2],['base','Degree=3','Degree=5'],loc='upper right')
plt.grid()
plt.show()
其结果如下:
常见的插值(拟合)方法有拉格朗日法,Neville迭代法,牛顿差商法等,还有特定场合下的Hermite插值、三次样条插值等,将在后续逐步展开介绍。