Na przykład, jak obliczyć pochodną funkcji
y = x 2 +1
używając numpy
?
Powiedzmy, że chcę mieć wartość pochodnej przy x = 5 ...
Na przykład, jak obliczyć pochodną funkcji
y = x 2 +1
używając numpy
?
Powiedzmy, że chcę mieć wartość pochodnej przy x = 5 ...
Odpowiedzi:
Masz cztery opcje
Skończone różnice nie wymagają zewnętrznych narzędzi, ale są podatne na błędy numeryczne, a jeśli jesteś w sytuacji wielowymiarowej, może to chwilę potrwać.
Zróżnicowanie symboliczne jest idealne, jeśli problem jest wystarczająco prosty. W dzisiejszych czasach metody symboliczne stają się coraz mocniejsze. SymPy to doskonały projekt do tego, który dobrze integruje się z NumPy. Spójrz na funkcje autowrap lub lambdify lub przeczytaj wpis na blogu Jensena dotyczący podobnego pytania .
Automatyczne pochodne są bardzo fajne, nie są podatne na błędy numeryczne, ale wymagają dodatkowych bibliotek (Google do tego jest kilka dobrych opcji). Jest to najbardziej solidny, ale także najbardziej wyrafinowany / trudny do skonfigurowania wybór. Jeśli możesz ograniczyć się do numpy
składni, Theano może być dobrym wyborem.
Oto przykład użycia 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.]
mpmath
(nie wiem jednak, co dokładnie robią).
Najprostszym sposobem, jaki przychodzi mi do głowy, jest użycie funkcji gradientu numpy :
x = numpy.linspace(0,10,1000)
dx = x[1]-x[0]
y = x**2 + 1
dydx = numpy.gradient(y, dx)
W ten sposób dydx zostanie obliczony przy użyciu różnic centralnych i będzie miał taką samą długość jak y, w przeciwieństwie do numpy.diff, który używa różnic do przodu i zwróci wektor rozmiaru (n-1).
dx
do numpy.gradient
zamiast x
? (ii) Czy możemy również wykonać ostatnią linię w następujący sposób dydx = numpy.gradient(y, numpy.gradient(x))
:?
NumPy nie zapewnia ogólnej funkcjonalności obliczania pochodnych. Może jednak obsługiwać prosty, specjalny przypadek wielomianów:
>>> 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żesz uciec od używania ilorazów centralnych różnic dla większości zastosowań. Dla pochodnej w jednym punkcie wzór wyglądałby mniej więcej tak
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 masz tablicę x
odciętych z odpowiednią tablicą y
wartości funkcji, możesz obliczyć przybliżenia pochodnych za pomocą
numpy.diff(y) / numpy.diff(x)
1 * x**2 + 1
. W 2
powyższym wierszu umieścili, ponieważ jest to wykładnik. Spójrz na to z daleka.
Zakładając, że chcesz użyć numpy
, możesz numerycznie obliczyć pochodną funkcji w dowolnym momencie, używając definicji Rygorystycznej :
def d_fun(x):
h = 1e-5 #in theory h is an infinitesimal
return (fun(x+h)-fun(x))/h
Aby uzyskać lepsze wyniki, możesz również użyć pochodnej symetrycznej :
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
Korzystając z Twojego przykładu, pełny kod powinien wyglądać mniej więcej tak:
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żesz numerycznie znaleźć pochodną pod adresem x=5
:
In [1]: d_fun(5)
Out[1]: 9.999999999621423
Rzucę inną metodę na stos ...
scipy.interpolate
Wiele interpolujących splajnów może zapewnić pochodne. Tak więc, używając liniowego splajnu ( k=1
), pochodna splajnu (przy użyciu derivative()
metody) powinna być równoważna różnicy w przód. Nie jestem do końca pewien, ale uważam, że użycie pochodnej sześciennej splajnu byłoby podobne do wyśrodkowanej pochodnej różnicy, ponieważ używa wartości przed i po do skonstruowania sześciennego splajnu.
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)
Aby obliczyć gradienty, społeczność uczenia maszynowego używa Autograd:
Żeby zainstalować:
pip install autograd
Oto przykład:
import autograd.numpy as np
from autograd import grad
def fct(x):
y = x**2+1
return y
grad_fct = grad(fct)
print(grad_fct(1.0))
Może również obliczać gradienty funkcji złożonych, np. Funkcji wielowymiarowych.
W zależności od wymaganego poziomu dokładności możesz to rozwiązać samodzielnie, 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 właściwie przyjąć granicy gradientu, ale to trochę zabawne. Musisz jednak uważać, ponieważ
>>> (((5+0.0000000000000001)**2+1)-((5)**2+1))/0.0000000000000001
0.0
Możesz użyć scipy
, co jest dość proste:
scipy.misc.derivative(func, x0, dx=1.0, n=1, args=(), order=3)
Znajdź n-tą pochodną funkcji w punkcie.
W Twoim przypadku:
from scipy.misc import derivative
def f(x):
return x**2 + 1
derivative(f, 5, dx=1e-6)
# 10.00000000139778