Musisz użyć Sympy: sympy.org/en/index.html Numpy to biblioteka obliczeń numerycznych dla Pythona
prrao
Alternatywnie, czy potrzebujesz metody szacowania wartości liczbowej instrumentu pochodnego? W tym celu możesz użyć metody różnic skończonych, ale pamiętaj, że zwykle są one strasznie hałaśliwe.
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 numpyskł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.]
Przepraszam, jeśli wydaje się to głupie, jakie są różnice między 3. różnicowaniem symbolicznym a różnicowaniem 4. ręcznym?
DrStrangeLove
11
Kiedy powiedziałem „symboliczne zróżnicowanie”, zamierzałem zasugerować, że procesem zajmuje się komputer. W zasadzie 3 i 4 różnią się tylko tym, kto wykonuje pracę, komputerem czy programistą. 3 jest preferowane zamiast 4 ze względu na spójność, skalowalność i lenistwo. 4 jest konieczne, jeśli 3 nie znajdzie rozwiązania.
MRocklin
4
W linii 7. utworzyliśmy funkcję f, która oblicza pochodną y wrt x. W 8 stosujemy tę pochodną funkcję do wektora wszystkich jedynek i otrzymujemy wektor wszystkich dwójek. Dzieje się tak, ponieważ, jak stwierdzono w wierszu 6, yprime = 2 * x.
MRocklin,
Dla zupełności można też dokonać różniczkowania przez całkowanie (patrz wzór całkowy Cauchy'ego), jest ono realizowane np. W mpmath(nie wiem jednak, co dokładnie robią).
DerWeh
Czy istnieje łatwy sposób na zrobienie skończonych różnic w numpy bez jego samodzielnego wdrażania? np. chcę znaleźć gradient funkcji w określonych punktach.
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).
@ weberc2, w takim przypadku powinieneś podzielić jeden wektor przez drugi, ale ręcznie traktować krawędzie osobno za pomocą pochodnych do przodu i do tyłu.
Sparkler
2
Lub możesz interpolować y ze stałą dx, a następnie obliczyć gradient.
IceArdor
@Sparkler Dzięki za sugestię. Jeśli mogę zadać 2 małe pytania, (i) dlaczego przechodzimy dxdo numpy.gradientzamiast x? (ii) Czy możemy również wykonać ostatnią linię w następujący sposób dydx = numpy.gradient(y, numpy.gradient(x)):?
user929304
2
Od wersji 1.13 niejednolite odstępy można określić, używając tablicy jako drugiego argumentu. Zobacz sekcję Przykłady na tej stronie .
Nathaniel Jones
28
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
21 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
„Obliczanie pochodnych numerycznych dla przypadku bardziej ogólnego jest łatwe” - nie zgadzam się, obliczanie pochodnych numerycznych dla przypadków ogólnych jest dość trudne. Po prostu wybrałeś ładnie działające funkcje.
Znak wysokiej wydajności
co oznacza 2 po >>> print p ?? (w drugiej linii)
DrStrangeLove
@DrStrangeLove: To jest wykładnik. Ma na celu symulowanie notacji matematycznej.
Sven Marnach
@SvenMarnach czy to maksymalny wykładnik ?? albo co?? Dlaczego myśli, że wykładnik wynosi 2? Wprowadziliśmy tylko współczynniki ...
DrStrangeLove
2
@DrStrangeLove: Wyjście powinno być odczytywane jako 1 * x**2 + 1. W 2powyższym wierszu umieścili, ponieważ jest to wykładnik. Spójrz na to z daleka.
Sven Marnach
15
Zakładając, że chcesz użyć numpy, możesz numerycznie obliczyć pochodną funkcji w dowolnym momencie, używając definicji Rygorystycznej :
defd_fun(x):
h = 1e-5#in theory h is an infinitesimalreturn (fun(x+h)-fun(x))/h
scipy.interpolateWiele 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)
właśnie próbowałem tego, wciąż otrzymuję błędy z tej funkcji AxisError: oś -1 jest poza zakresem dla tablicy wymiaru 0 i nie widzę żadnych odpowiedzi na to również w społeczności, jakaś pomoc?
Ayan Mitra
Opublikuj swój problem jako nowe pytanie i łącze do niego tutaj. Prawdopodobnie potrzebne będzie podanie przykładu powodującego wystąpienie błędu. Błędy, które mam z funkcjami interp są zwykle spowodowane tym, że dane nie są dobrze uformowane - jak powtarzające się wartości, zła liczba wymiarów, jedna z tablic jest przypadkowo pusta, dane nie są sortowane względem x lub gdy posortowane poprawna funkcja itp. Możliwe, że scipy wywołuje numpy niepoprawnie, ale jest bardzo mało prawdopodobne. Sprawdź x.shape i y.shape. Sprawdź, czy działa np.interp () - może dostarczyć bardziej pomocnego błędu, jeśli nie.
flutefreak7
6
Aby obliczyć gradienty, społeczność uczenia maszynowego używa Autograd:
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.]
źródło
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).
źródło
dx
donumpy.gradient
zamiastx
? (ii) Czy możemy również wykonać ostatnią linię w następujący sposóbdydx = 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ąźródło
1 * x**2 + 1
. W2
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
źródło
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życiuderivative()
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)
źródło
Aby obliczyć gradienty, społeczność uczenia maszynowego używa Autograd:
Żeby zainstalować:
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.
źródło
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
źródło
Możesz użyć
scipy
, co jest dość proste:scipy.misc.derivative(func, x0, dx=1.0, n=1, args=(), order=3)
W Twoim przypadku:
from scipy.misc import derivative def f(x): return x**2 + 1 derivative(f, 5, dx=1e-6) # 10.00000000139778
źródło