2012-03-26 17 views
47

Come si calcola la derivata di una funzione, ad esempioCome si calcola la derivata usando Numpy?

y = x +1

utilizzando numpy?

Diciamo, voglio che il valore della derivata in x = 5 ...

+3

è necessario utilizzare Sympy: http://sympy.org/en/index.html Numpy è un calcolo numerico libreria per Python – prrao

+0

In alternativa, si desidera un metodo per stimare il valore numerico della derivata? Per questo è possibile utilizzare un metodo di differenza finita, ma tenere presente che tendono ad essere orribilmente rumoroso. –

risposta

88

si hanno quattro opzioni

  1. È possibile utilizzare Finite Differences
  2. È possibile utilizzare Automatic Derivatives
  3. È possibile utilizzare Symbolic Differentiation
  4. È possibile calcolare derivati ​​da mano.

Le differenze finite non richiedono strumenti esterni ma sono soggette a errori numerici e, se ci si trova in una situazione multivariata, può richiedere un po 'di tempo.

La differenziazione simbolica è ideale se il tuo problema è abbastanza semplice. Al giorno d'oggi i metodi simbolici stanno diventando piuttosto robusti. SymPy è un eccellente progetto per questo che si integra bene con NumPy. Guarda le funzioni autowrap o lambdify o controlla Jensen's blogpost about a similar question.

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 impostare. Se si sta bene limitandosi alla sintassi numpy, allora Theano potrebbe essere una buona scelta.

Ecco un esempio utilizzando 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

Scusa, se questo sembra stupido, quali sono le differenze tra 3.Differenziazione simbolica e 4.differenza della mano? – DrStrangeLove

+8

Quando ho detto "differenziazione simbolica" intendevo dire che il processo era gestito da un computer. In linea di principio 3 e 4 differiscono solo da chi fa il lavoro, il computer o il programmatore. 3 è preferibile a 4 per coerenza, scalabilità e pigrizia. 4 è necessario se 3 non riesce a trovare una soluzione. – MRocklin

+1

Grazie mille !! Ma cosa è [2. 2. 2. 2. 2.] all'ultima riga ?? – DrStrangeLove

22

NumPy non fornisce funzionalità generale per calcolare derivati. Può gestisce il semplice caso particolare di polinomi però:

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

Se si vuole calcolare la derivata numerica, è possibile ottenere via con l'utilizzo di rapporti incrementali centrali per la maggior parte delle applicazioni. Per il derivato in un unico punto, la formula sarà 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 si dispone di una matrice x di ascisse con una corrispondente matrice y dei valori di funzione, è possibile COMPUT approssimazioni di derivati ​​con

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

'Computare derivati ​​numerici per casi più generali è facile' - Mi permetto di dissentire, calcolare i derivati ​​numerici per casi generali è piuttosto difficile. Hai appena scelto funzioni ben educate. –

+0

cosa significa 2 dopo >>> print p ?? (sulla seconda riga) – DrStrangeLove

+0

@DrStrangeLove: Questo è l'esponente. Ha lo scopo di simulare la notazione matematica. –

2

a seconda del livello di precisione si richiede è possibile lavorare fuori da soli, utilizzando il 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 è un po 'divertente. Devi guardare fuori, però, perché

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

Il modo più straight-forward posso pensare utilizza numpy's gradient function:

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

questo modo, dydx sarà calcolato utilizzando differenze centrali e volontà hanno la stessa lunghezza di y, a differenza di numpy.diff, che usa le differenze in avanti e restituirà (n-1) il vettore di dimensione.

+0

Cosa succede se dx non è costante? – weberc2

+2

@ weberc2, in questo caso dovresti dividere un vettore con un altro, ma trattare i bordi separatamente con le derivate avanti e indietro manualmente. – Sparkler

+1

Oppure è possibile interpolare y con una costante dx, quindi calcolare il gradiente. – IceArdor

3

mi butto un altro metodo sul mucchio ...

s' scipy.interpolate molti spline di interpolazione sono in grado di fornire strumenti derivati. Quindi, utilizzando una spline lineare (k=1), la derivata della spline (utilizzando il metodo derivative()) dovrebbe essere equivalente a una differenza di inoltro. Non ne sono del tutto sicuro, ma credo che l'uso di un derivato spline cubico 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) 
2

Supponendo che si desidera utilizzare numpy, è possibile numericamente calcolare la derivata di una funzione in qualsiasi momento utilizzando il Rigorous definition:

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

È anche possibile utilizzare il Symmetric derivative per ottenere risultati migliori:

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

Utilizzando l'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, è possibile numericamente trovare la derivata in x=5:

In [1]: d_fun(5) 
Out[1]: 9.999999999621423 
Problemi correlati