Istnieje kilka problemów.
Pierwszym problemem jest kolejność wartości x. Z dokumentacji dla scipy.interpolate.UnivariateSpline
można znaleźć
x : (N,) array_like
1-D array of independent input data. MUST BE INCREASING.
Stres dodany przeze mnie. Dane podane przez x są w odwrotnej kolejności. Do debugowania tego jest przydatne użycie "normalnego" splajnu, aby upewnić się, że wszystko ma sens.
Drugi numer, a drugi bardziej bezpośrednio związany z Twoim problemem, odnosi się do parametru s. Co to robi? Ponownie z dokumentacją znaleźć
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.
Więc ów określa jak blisko interpolowane krzywa musi dojść do punktów danych, w sensie najmniejszych kwadratów. Jeśli ustawimy wartość bardzo dużą, splajn nie musi zbliżać się do punktów danych.
Jako kompletny przykład rozważyć następujące
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()
Czy masz APRIORI wiedzę na temat danych, na którym pracujemy? Może być teoretyczną reprezentacją? Czy możesz uzyskać więcej danych? 50 lub 100 punktów? – twil
@twil: Nie. Dane pochodzą z eksperymentu z udziałem ludzkich decyzji. To wszystko co wiem. Próbuję dopasować krzywą w celu ekstrapolacji do dalszych wartości x. Próbowałem sześciennych splajnów i polyfitów, ale one też nie są dobre. Czy robię coś nie tak z wyborem funkcji wygładzania powyżej w UnivariateSpline? –
Robisz dobrze, ale musisz trochę danych. Powiedziałbym, że wartości przy 3 i 13 nie są "normalne". Jeśli je usuniesz, uzyskasz lepszą krzywiznę? Ale bez żadnej wiedzy i założeń dotyczących procesu nie jest to uczciwe :) – twil