2013-01-16 16 views
6

Mam trochę problemów z dopasowaniem krzywej do niektórych danych, ale nie mogę wykombinować, gdzie idę źle.Wykładnicze dopasowanie krzywej zaniku w numpy i scipy

W przeszłości Zrobiłem to z numpy.linalg.lstsq dla funkcji wykładniczej i scipy.optimize.curve_fit dla funkcji sigmoidowych. Tym razem chciałem stworzyć skrypt, który pozwoliłby mi określić różne funkcje, określić parametry i przetestować ich dopasowanie względem danych. Robiąc to zauważyłem, że Scipy leastsq i Numpy lstsq wydają się zapewniać różne odpowiedzi dla tego samego zestawu danych i tej samej funkcji. Funkcja jest po prostu y = e^(l*x) i jest ograniczona tak, że y=1 w x=0.

Linia trendu programu Excel zgadza się z wynikiem Numpy lstsq, ale ponieważ Scipy leastsq może pełnić jakąkolwiek funkcję, dobrze byłoby ustalić, na czym polega problem.

import scipy.optimize as optimize 
import numpy as np 
import matplotlib.pyplot as plt 

## Sampled data 
x = np.array([0, 14, 37, 975, 2013, 2095, 2147]) 
y = np.array([1.0, 0.764317544, 0.647136491, 0.070803763, 0.003630962,  0.001485394,  0.000495131]) 

# function 
fp = lambda p, x: np.exp(p*x) 

# error function 
e = lambda p, x, y: (fp(p, x) - y) 

# using scipy least squares 
l1, s = optimize.leastsq(e, -0.004, args=(x,y)) 
print l1 
# [-0.0132281] 


# using numpy least squares 
l2 = np.linalg.lstsq(np.vstack([x, np.zeros(len(x))]).T,np.log(y))[0][0] 
print l2 
# -0.00313461628963 (same answer as Excel trend line) 

# smooth x for plotting 
x_ = np.arange(0, x[-1], 0.2) 

plt.figure() 
plt.plot(x, y, 'rx', x_, fp(l1, x_), 'b-', x_, fp(l2, x_), 'g-') 
plt.show() 

Edycja - informacja dodatkowa

MWE powyżej zawiera małą próbkę zbiorze danych. Podczas dopasowywania rzeczywistych danych krzywa przedstawia R^2 0,82, podczas gdy krzywa numpy.linalg.lstsq, która jest taka sama, jak obliczona przez Excel, ma wartość R^2 wynoszącą 0,41. .

Odpowiedz

4

Minimalizujesz różne funkcje błędów.

Podczas korzystania numpy.linalg.lstsq, funkcja błędu jest zminimalizowany jest

np.sum((np.log(y) - p * x)**2) 

podczas scipy.optimize.leastsq minimalizuje funkcję

np.sum((y - np.exp(p * x))**2) 

Pierwszy przypadek wymaga liniową zależność pomiędzy zależnymi i niezależnymi zmiennymi, ale rozwiązanie jest znane analitycznie, podczas gdy drugie może obsłużyć dowolną zależność, ale opiera się na iteracyjnej metodzie.

Na odrębnej notatce nie mogę przetestować go teraz, ale podczas korzystania numpy.linalg.lstsq, że nie trzeba do vstack rząd zer, następujące prace, a także:

l2 = np.linalg.lstsq(x[:, None], np.log(y))[0][0] 
+0

Dzięki @Jaime - świetna odpowiedź!Niestety moja znajomość matematyki nie jest tak wielka; czy ktoś pisze lub źle [patrz także edytuj powyżej], czy są one po prostu zasadniczo różne ...? Jakie są implikacje dla innych funkcji, na przykład, gdybym chciał przetestować dopasowanie krzywej Sigmoid lub Gompertz do tych samych danych? – StacyR

+0

@StacyR Nie mam wiedzy, aby właściwie odpowiedzieć na twoje pytanie, ale jestem całkiem pewny, że dopasowanie wykładniczej, jak to zrobiłeś z 'np.linalg.lstsq' jest po prostu szybką i niecałkowitą sztuczką, która nie jest obliczana błędy prawidłowo. Jest tu pewna dyskusja (trudna do naśladowania) tutaj: http://mathworld.wolfram.com/LeastSquaresFittingExponential.html Jeśli nie chcesz zanurzyć się naprawdę głęboko w te rzeczy, poszedłbym z metodą scipy na wszystko: to powinien dawać lepsze dopasowania, a twoje wyniki będą spójne dla wszystkich funkcji. – Jaime

+0

dzięki jeszcze raz! Zrobiłem trochę więcej badań na ten temat i, jak wspomniałeś, odkryłem, że metoda 'np.linalg.lstsq' nadmiernie obciąża błędy y przy niskich wartościach x. Udostępniony przeze mnie link i kilka innych zasobów, które znalazłem, pozwoliły mi wyprowadzić jedną inną metodę analityczną (rzeczą, która sprawia, że ​​jest to trudne jest ograniczenie - wszystkie książki opisują metodę dla y = a * e^b * x raczej niż y = e^b * x), jednak powoduje to również gorszą krzywą dopasowania niż iteracyjne 'scipy.optimize.leastsq'. – StacyR

1

Aby wyjaśniają nieco punkt Jaime'a, każda nieliniowa transformacja danych doprowadzi do innej funkcji błędu, a tym samym do różnych rozwiązań. Prowadzi to do różnych przedziałów ufności dla parametrów dopasowania. Masz więc trzy możliwe kryteria do podjęcia decyzji: który błąd chcesz zminimalizować, które parametry chcesz mieć więcej zaufania, a na końcu, jeśli używasz dopasowania do przewidywania wartości, która to metoda daje mniej błędów w interesującym przewidywana wartość. Odtwarzanie trochę analitycznie iw Excelu sugeruje, że różne rodzaje szumu w danych (np. Jeśli funkcja szumów skaluje amplitudę, wpływa na stałą czasową lub jest addytywna) prowadzi do różnych wyborów rozwiązania.

Dodam również, że podczas gdy ta sztuczka "działa" dla wykładniczego zaniku do 0, nie można jej użyć w bardziej ogólnym (i pospolitym) przypadku tłumionych wykładników (rosnących lub opadających) do wartości, które nie mogą być zakłada się, że wynosi 0.

Powiązane problemy