2012-03-26 14 views
47

Jak można obliczyć pochodną, ​​na przykład zJak obliczyć pochodną za pomocą Numpy?

y = x +1

pomocą numpy?

Powiedzmy, chcę wartość pochodnej w punkcie x = 5 ...

+3

Trzeba użyć Sympy: http://sympy.org/en/index.html Numpy jest Obliczenia numeryczne biblioteka dla Pythona – prrao

+0

Alternatywnie, czy chcesz zastosować metodę szacowania wartości liczbowej pochodnej? Do tego możesz użyć metody skończonej różnicy, ale pamiętaj, że są one okropnie hałaśliwe. –

Odpowiedz

88

Masz cztery opcje

  1. Można użyć Finite Differences
  2. Można użyć Automatic Derivatives
  3. Można użyć Symbolic Differentiation
  4. Można obliczyć pochodne przez dłoń.

Różnice skończone nie wymagają zewnętrznych narzędzi, ale są podatne na błędy numeryczne i, jeśli jesteś w sytuacji wielowymiarowej, mogą trochę potrwać.

Symboliczne zróżnicowanie jest idealne, jeśli problem jest wystarczająco prosty. W dzisiejszych czasach metody symboliczne stają się coraz bardziej niezawodne. SymPy to doskonały projekt do tego, który dobrze integruje się z NumPy. Sprawdź funkcje autowrap lub lambdify lub sprawdź Jensen's blogpost about a similar question.

Automatyczne pochodne są bardzo fajne, nie są podatne na błędy numeryczne, ale wymagają pewnych dodatkowych bibliotek (google, jest kilka dobrych opcji). Jest to najbardziej wytrzymały, ale także najbardziej wyrafinowany/trudny do skonfigurowania wybór. Jeśli możesz ograniczyć się do składni numpy, to dobrym wyborem może być Theano.

Oto przykład przy użyciu SymPy

In [1]: from sympy import * 
In [2]: import numpy as np 
In [3]: x = Symbol('x') 
In [4]: y = x**2 + 1 
In [5]: yprime = y.diff(x) 
In [6]: yprime 
Out[6]: 2⋅x 

In [7]: f = lambdify(x, yprime, 'numpy') 
In [8]: f(np.ones(5)) 
Out[8]: [ 2. 2. 2. 2. 2.] 
+0

Przepraszam, jeśli to wydaje się głupie, Jakie są różnice między 3.Symboliczne zróżnicowanie i 4. przez różnicowanie rąk? – DrStrangeLove

+8

Kiedy powiedziałem "symboliczne zróżnicowanie", zamierzałem sugerować, że proces był obsługiwany przez komputer. Zasadniczo 3 i 4 różnią się tylko tym, kto wykonuje pracę, komputer lub programista. 3 jest bardziej korzystne niż 4 ze względu na konsystencję, skalowalność i lenistwo. 4 jest konieczne, jeśli 3 nie znajdzie rozwiązania. – MRocklin

+1

Wielkie dzięki! Ale co to jest [2. 2. 2. 2. 2.] na ostatniej linii? – DrStrangeLove

22

NumPy nie przewiduje ogólną funkcjonalność obliczyć pochodne. Można go obsługuje prosty szczególny przypadek wielomianów jednakże:

>>> p = numpy.poly1d([1, 0, 1]) 
>>> print p 
    2 
1 x + 1 
>>> q = p.deriv() 
>>> print q 
2 x 
>>> q(5) 
10 

Jeśli chcesz obliczyć pochodną numerycznie, można uciec z wykorzystaniem centralnych ilorazów różnicowych dla większości zastosowań. Dla pochodnej w jednym punkcie, wzór będzie coś podobnego

x = 5.0 
eps = numpy.sqrt(numpy.finfo(float).eps) * (1.0 + x) 
print (p(x + eps) - p(x - eps))/(2.0 * eps * x) 

jeśli tablicę x odciętych z odpowiedniego układu y wartości funkcji można Comput aproksymacje pochodnych z

numpy.diff(y)/numpy.diff(x) 
+2

"Obliczanie pochodnych numerycznych dla bardziej ogólnych przypadków jest łatwe" - Błagam, aby się różnić, obliczanie pochodnych numerycznych dla ogólnych przypadków jest dość trudne. Właśnie wybrałeś ładnie zachowane funkcje. –

+0

co znaczy 2 po >>> drukuj p ?? (w drugiej linii) – DrStrangeLove

+0

@DrStrangeLove: To jest wykładnik. Ma na celu symulację zapisu matematycznego. –

2

zależności od poziomu dokładności jest potrzebna można pracować to sam, korzystając z prostego dowodu różnicowania:

>>> (((5 + 0.1) ** 2 + 1) - ((5) ** 2 + 1))/0.1 
10.09999999999998 
>>> (((5 + 0.01) ** 2 + 1) - ((5) ** 2 + 1))/0.01 
10.009999999999764 
>>> (((5 + 0.0000000001) ** 2 + 1) - ((5) ** 2 + 1))/0.0000000001 
10.00000082740371 

nie możemy faktycznie przekroczyć granicy gradientu, ale jest to zabawne. Musisz uważać, choć ze względu

>>> (((5+0.0000000000000001)**2+1)-((5)**2+1))/0.0000000000000001 
0.0 
18

Najbardziej prosta sposób mogę myśleć korzysta numpy's gradient function:

x = numpy.linspace(0,10,1000) 
dx = x[1]-x[0] 
y = x**2 + 1 
dydx = numpy.gradient(y, dx) 

ten sposób dydx będą obliczane za pomocą różnic centralnych i będzie mają tę samą długość co y, w przeciwieństwie do numpy.diff, która używa różnic naprzód i zwraca wektor wielkości (n-1).

+0

Co zrobić, jeśli dx nie jest stały? – weberc2

+2

@ weberc2, w takim przypadku należy podzielić jeden wektor na inny, ale ręcznie traktować krawędzie osobno za pomocą pochodnych do przodu i do tyłu. – Sparkler

+1

Lub możesz interpolować y ze stałą dx, a następnie obliczyć gradient. – IceArdor

3

dorzucę innej metody na stosie ...

scipy.interpolate „s wielu wypusty interpolację są w stanie zapewnić pochodne. Tak więc, używając liniowego splajnu (k=1), pochodna splajnu (przy użyciu metody derivative()) powinna być równoważna różnicy naprzód. Nie jestem do końca pewien, ale sądzę, że użycie pochodnej sześciennej splajnu byłoby podobne do pochodnej z wyśrodkowaną różnicą, ponieważ wykorzystuje wartości z przed i po konstruowaniu splajnu sześciennego.

from scipy.interpolate import InterpolatedUnivariateSpline 

# Get a function that evaluates the linear spline at any x 
f = InterpolatedUnivariateSpline(x, y, k=1) 

# Get a function that evaluates the derivative of the linear spline at any x 
dfdx = f.derivative() 

# Evaluate the derivative dydx at each x location... 
dydx = dfdx(x) 
2

Zakładając chcesz użyć numpy można numerycznie obliczyć pochodną funkcji w dowolnym momencie za pomocą Rigorous definition:

def d_fun(x): 
    h = 1e-5 #in theory h is an infinitesimal 
    return (fun(x+h)-fun(x))/h 

Można również użyć Symmetric derivative lepszych wyników:

def d_fun(x): 
    h = 1e-5 
    return (fun(x+h)-fun(x-h))/(2*h) 

Na tym przykładzie pełny kod powinien wyglądać następująco:

def fun(x): 
    return x**2 + 1 

def d_fun(x): 
    h = 1e-5 
    return (fun(x+h)-fun(x-h))/(2*h) 

Teraz można numerycznie znaleźć pochodną w x=5:

In [1]: d_fun(5) 
Out[1]: 9.999999999621423 
Powiązane problemy