Come calcolo la derivata di una funzione, ad esempio
y = x 2 +1
usando numpy
?
Diciamo, voglio il valore della derivata in x = 5 ...
Come calcolo la derivata di una funzione, ad esempio
y = x 2 +1
usando numpy
?
Diciamo, voglio il valore della derivata in x = 5 ...
Risposte:
Hai quattro opzioni
Le differenze finite non richiedono strumenti esterni ma sono soggette a errori numerici e, se ti trovi in una situazione multivariata, può richiedere del tempo.
La differenziazione simbolica è l'ideale se il tuo problema è abbastanza semplice. I metodi simbolici stanno diventando piuttosto robusti in questi giorni. SymPy è un ottimo progetto per questo che si integra bene con NumPy. Guarda le funzioni autowrap o lambdify o dai un'occhiata al blogpost di Jensen su una domanda simile .
Le derivate automatiche sono molto interessanti, non sono soggette a errori numerici, ma richiedono alcune librerie aggiuntive (google per questo, ci sono alcune buone opzioni). Questa è la scelta più robusta ma anche la più sofisticata / difficile da configurare. Se stai bene limitandoti alla numpy
sintassi, Theano potrebbe essere una buona scelta.
Ecco un esempio che utilizza 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
(non sono sicuro però cosa fanno esattamente).
Il modo più diretto a cui posso pensare è usare la funzione gradiente di numpy :
x = numpy.linspace(0,10,1000)
dx = x[1]-x[0]
y = x**2 + 1
dydx = numpy.gradient(y, dx)
In questo modo, dydx verrà calcolato utilizzando differenze centrali e avrà la stessa lunghezza di y, a differenza di numpy.diff, che utilizza differenze dirette e restituirà il vettore di dimensione (n-1).
dx
a numpy.gradient
invece di x
? (ii) Possiamo anche fare l'ultima tua riga come segue dydx = numpy.gradient(y, numpy.gradient(x))
:?
NumPy non fornisce funzionalità generali per calcolare i derivati. Tuttavia, può gestire il semplice caso speciale dei polinomi:
>>> p = numpy.poly1d([1, 0, 1])
>>> print p
2
1 x + 1
>>> q = p.deriv()
>>> print q
2 x
>>> q(5)
10
Se vuoi calcolare la derivata numericamente, puoi cavartela usando i quozienti di differenza centrali per la stragrande maggioranza delle applicazioni. Per la derivata in un unico punto, la formula sarebbe qualcosa di simile
x = 5.0
eps = numpy.sqrt(numpy.finfo(float).eps) * (1.0 + x)
print (p(x + eps) - p(x - eps)) / (2.0 * eps * x)
se hai un array x
di ascisse con un array corrispondente y
di valori di funzione, puoi calcolare approssimazioni di derivate con
numpy.diff(y) / numpy.diff(x)
1 * x**2 + 1
. Mettono il 2
nella riga sopra perché è un esponente. Guardalo da lontano.
Supponendo che si desideri utilizzare numpy
, è possibile calcolare numericamente la derivata di una funzione in qualsiasi punto utilizzando la definizione rigorosa :
def d_fun(x):
h = 1e-5 #in theory h is an infinitesimal
return (fun(x+h)-fun(x))/h
Puoi anche utilizzare la derivata simmetrica per risultati migliori:
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
Usando il tuo esempio, il codice completo dovrebbe essere simile a:
def fun(x):
return x**2 + 1
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
Ora puoi trovare numericamente la derivata in x=5
:
In [1]: d_fun(5)
Out[1]: 9.999999999621423
Metterò un altro metodo sul mucchio ...
scipy.interpolate
Le numerose spline interpolanti sono in grado di fornire derivati. Quindi, usando una spline lineare ( k=1
), la derivata della spline (usando il derivative()
metodo) dovrebbe essere equivalente a una differenza diretta. Non sono del tutto sicuro, ma credo che l'utilizzo di una derivata spline cubica sarebbe simile a una derivata della differenza centrata poiché utilizza i valori di prima e dopo per costruire la spline cubica.
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)
Per calcolare i gradienti, la comunità di machine learning utilizza Autograd:
" Calcola in modo efficiente i derivati del codice numpy. "
Installare:
pip install autograd
Ecco un esempio:
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))
Può anche calcolare gradienti di funzioni complesse, ad esempio funzioni multivariate.
A seconda del livello di precisione richiesto, puoi elaborarlo da solo, utilizzando la semplice prova di differenziazione:
>>> (((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
non possiamo effettivamente prendere il limite del gradiente, ma è piuttosto divertente. Devi stare attento però perché
>>> (((5+0.0000000000000001)**2+1)-((5)**2+1))/0.0000000000000001
0.0
Puoi usare scipy
, che è abbastanza semplice:
scipy.misc.derivative(func, x0, dx=1.0, n=1, args=(), order=3)
Trova l'ennesima derivata di una funzione in un punto.
Nel tuo caso:
from scipy.misc import derivative
def f(x):
return x**2 + 1
derivative(f, 5, dx=1e-6)
# 10.00000000139778