Короткий ответ: если вас интересуют коэффициенты полинома в стандартной степени мощности, вам лучше использовать CubicSpline
(и см. это обсуждение ):
cu = scipy.interpolate.CubicSpline(x_sample, d_sample)
plt.plot(x_sample, y_sample, 'ko')
for i in range(len(cu.x)-1):
xs = np.linspace(cu.x[i], cu.x[i+1], 100)
plt.plot(xs, np.polyval(cu.c[:,i], xs - cu.x[i]))
И чтобы ответить на ваш вопрос, вы можете вместо этого создать кусочную функцию, используя numpy.piecewise
, точки останова в cu.x
и коэффициенты в cu.c
, либо либо непосредственно кодируйте полиномиальные выражения самостоятельно, либо используйте numpy.polyval
. Например,
cu.c[:,0] # coeffs for 0th segment
# array([-0.01316353, -0.02680068, 0.51629024, 3. ])
# equivalent ways to code polynomial for this segment
f0 = lambda x: cu.c[0,0]*(x-x[0])**3 + cu.c[1,0]*(x-x[0])**2 + cu.c[2,0]*(x-x[0]) + cu.c[3,0]
f0 = lambda x: [cu.c[i,0]*(x-x[0])**(3-i) for i in range(4)]
# ... or getting values directly from x's
y0 = np.polyval(cu.c[:,0], xs - cu.x[0])
БОЛЬШОЙ ОТВЕТ:
Здесь есть несколько точек возможной путаницы:
UnivariateSpline
подходит B-сплайн , поэтому коэффициенты не совпадают со стандартным полиномиальным базисом - . Для преобразования из B-сплайна мы можем использовать
PPoly.from_spline
, но, к сожалению UnivariateSpline
возвращает усеченный список узлов и коэффициентов, которые не будут играть с этой функцией. Мы можем решить эту проблему, обратившись к внутренним данным объекта сплайна, что является небольшим табу. - Кроме того, матрица коэффициентов
c
(от UnivariateSpline
или CubicSpline
) имеет обратную степень заказать и предполагает, что вы «центрируете» себя, например, коэффициент в c[k,i]
принадлежит c[k,i]*(x-x[i])^(3-k)
.
Учитывая ваши настройки, обратите внимание, что если вместо использования оболочки UnivariateSpline, мы напрямую подходим с splrep
и без сглаживания (s=0
), мы можем захватить кортеж tck
(knots-coefficients coele) и отправить его в функцию PPoly.from_spline
и получить нужные нам коэффициенты:
tck = scipy.interpolate.splrep(x_sample, d_sample, s=0)
tck
# (array([0. , 0. , 0. , 0. , 2.68456376,
# 4.02684564, 5.36912752, 6.7114094 , 9.39597315, 9.39597315,
# 9.39597315, 9.39597315]),
# array([3. , 3.46200469, 4.05843704, 3.89649312, 3.33792889,
# 2.29435138, 1.65015175, 1.59021688, 0. , 0. ,
# 0. , 0. ]),
# 3)
p = scipy.interpolate.PPoly.from_spline(tck)
p.x.shape # breakpoints in unexpected shape
# (12,)
p.c.shape # polynomial coeffs in unexpected shape
# (4, 11)
Обратите внимание на странные повторяющиеся точки останова в tck
и снова в p.x
: это вещь FITPACK (алгоритм, выполняющий все это).
Если мы пытаемся отправить кортеж tck
из UnivariateSpline с (s.get_knots(), s.get_coeffs(), 3)
, мы пропускаем эти повторы, поэтому from_spline
не работает. Извлеките источник , хотя кажется, что полный вектор хранится в self._data
, поэтому мы можем сделать
s = scipy.interpolate.UnivariateSpline(x_sample, d_sample, s=0)
tck = (s._data[8], s._data[9], 3)
p = scipy.interpolate.PPoly.from_spline(tck)
и получить то же, что и раньше. Чтобы проверить эти коэффициенты, работайте:
plt.plot(x_sample, d_sample, 'o')
for i in range(len(p.x)-1):
xs = np.linspace(p.x[i], p.x[i+1], 10)
plt.plot(xs, np.polyval(p.c[:,i], xs - p.x[i]))
Примечание numpy.polyval
требует обратного порядка для коэффициентов, чтобы мы могли передать p.c
как есть.