我有一个实验数据,我试图在scipy中使用UnivariateSpline函数来拟合曲线。数据如下:
x y
13 2.404070
12 1.588134
11 1.760112
10 1.771360
09 1.860087
08 1.955789
07 1.910408
06 1.655911
05 1.778952
04 2.624719
03 1.698099
02 3.022607
01 3.303135
这是我正在做的事情:
import matplotlib.pyplot as plt
from scipy import interpolate
yinterp = interpolate.UnivariateSpline(x, y, s = 5e8)(x)
plt.plot(x, y, 'bo', label = 'Original')
plt.plot(x, yinterp, 'r', label = 'Interpolated')
plt.show()
它的外观如下:
我想知道是否有人考虑过scipy可能有的其他曲线拟合选项?我比较狡猾。
谢谢!
答案 0 :(得分:39)
有一些问题。
第一个问题是x值的顺序。从我们找到的scipy.interpolate.UnivariateSpline
文档
x : (N,) array_like
1-D array of independent input data. MUST BE INCREASING.
我的压力增加了。对于您给出的数据,x的顺序相反。 要调试它,使用“普通”样条曲线来确保一切都有意义是很有用的。
第二个问题,以及与您的问题更直接相关的问题,与s参数有关。它有什么作用?再次从我们找到的文档中
s : float or None, optional
Positive smoothing factor used to choose the number of knots. Number
of knots will be increased until the smoothing condition is satisfied:
sum((w[i]*(y[i]-s(x[i])))**2,axis=0) <= s
If None (default), s=len(w) which should be a good value if 1/w[i] is
an estimate of the standard deviation of y[i]. If 0, spline will
interpolate through all data points.
因此,在最小二乘意义上,s确定插值曲线必须与数据点的接近程度。如果我们将值设置得非常大,那么样条曲线不需要靠近数据点。
作为一个完整的例子,请考虑以下内容
import scipy.interpolate as inter
import numpy as np
import pylab as plt
x = np.array([13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
y = np.array([2.404070, 1.588134, 1.760112, 1.771360, 1.860087,
1.955789, 1.910408, 1.655911, 1.778952, 2.624719,
1.698099, 3.022607, 3.303135])
xx = np.arange(1,13.01,0.1)
s1 = inter.InterpolatedUnivariateSpline (x, y)
s1rev = inter.InterpolatedUnivariateSpline (x[::-1], y[::-1])
# Use a smallish value for s
s2 = inter.UnivariateSpline (x[::-1], y[::-1], s=0.1)
s2crazy = inter.UnivariateSpline (x[::-1], y[::-1], s=5e8)
plt.plot (x, y, 'bo', label='Data')
plt.plot (xx, s1(xx), 'k-', label='Spline, wrong order')
plt.plot (xx, s1rev(xx), 'k--', label='Spline, correct order')
plt.plot (xx, s2(xx), 'r-', label='Spline, fit')
# Uncomment to get the poor fit.
#plt.plot (xx, s2crazy(xx), 'r--', label='Spline, fit, s=5e8')
plt.minorticks_on()
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.show()