我有一组描述简单表面腔/凸起的横截面的点。多项式逼近就足够了,但 numpy.polyfit 需要一定程度。我想到了不同程度的几次迭代来选择具有最小平均残差的迭代。是否有任何现有功能或更好的方法来获得良好的曲线?计算时间非常重要:数据集很小(大约20个点),但有数千个。
最初的任务是在非常离散的表面上找到这些空洞测地线 - 是否存在任何更简单的方法?
答案 0 :(得分:2)
除非我弄错了,否则你总会获得最大允许的最小残差。如果您允许优化程序选择d
度,则会选择无限大d
,但实际上它会在d = dof
dof
时停止,其中import numpy as np
from numpy.polynomial import polynomial as poly
from scipy import interpolate as interp
import matplotlib.pyplot as plt
n = 20
x = np.linspace(0, 2*np.pi, n)
a = np.sin(x) + np.random.uniform(-.2, .2, n)
s = interp.UnivariateSpline(x, a)
p = poly.polyfit(x, a, 3)
p = poly.Polynomial(p)
plt.figure()
plt.plot(x, np.sin(x), '-', x, a, 'o', x, s(x), '--', x, p(x), '.-')
是您的拟合自由度(基本上是数据点的数量),此时您将获得零残差。
如果你对拟合的真正功能形式并不感兴趣而只想要曲线,你可以使用scipy.interpolate
module来研究插值,这对于你可能正在做的事情类型更灵活
如果速度很重要且格式不重要,只需尝试np.polynomial.polynomial.polyfit
一定程度的scipy.interpolate.UnivariateSpline
,然后{{3}},看看哪个更快。
在我看来,样条曲线要快得多,而且对于我的例子,它们给出了相同的结果(记住,样条曲线基本上只是多项式串联在一起)
In [32]: timeit s = interp.UnivariateSpline(x, a)
10000 loops, best of 3: 22.1 µs per loop
In [33]: timeit p = poly.Polynomial(poly.polyfit(x, a, 3))
1000 loops, best of 3: 392 µs per loop
In [34]: timeit p = poly.polyfit(x, a, 3)
1000 loops, best of 3: 311 µs per loop
In [35]: timeit interp.UnivariateSpline(x, a)(x)
10000 loops, best of 3: 44.9 µs per loop
In [37]: timeit poly.Polynomial(poly.polyfit(x, a, 3))(x)
1000 loops, best of 3: 470 µs per loop
包括评估:
d >= dof
为了好玩,为了说明过度拟合的概念,这是一个带有p = poly.Polynomial(poly.polyfit(x, a, x.size-1))
plot(x, np.sin(x), '-', x, a, 'o', x, p(x), ':')
的多项式:
{{1}}