2012-03-26 22 views
47

¿Cómo se calcula la derivada de una función, por ejemplo¿Cómo calculo el derivado usando Numpy?

y = x +1

usando numpy?

Digamos, quiero que el valor de la derivada en x = 5 ...

+3

Es necesario utilizar sympy: http://sympy.org/en/index.html Numpy es un cálculo numérico biblioteca para Python – prrao

+0

Alternativamente, ¿quiere un método para estimar el valor numérico de la derivada? Para esto puedes usar un método de diferencia finita, pero ten en cuenta que tienden a ser terriblemente ruidoso. –

Respuesta

88

tiene cuatro opciones

  1. Puede utilizar Finite Differences
  2. Puede utilizar Automatic Derivatives
  3. Puede utilizar Symbolic Differentiation
  4. Puede calcular los derivados de mano.

Las diferencias finitas no requieren herramientas externas, pero son propensas a errores numéricos y, si se encuentra en una situación multivariada, pueden tardar un tiempo.

La diferenciación simbólica es ideal si su problema es lo suficientemente simple. Los métodos simbólicos se están volviendo bastante sólidos en estos días. SymPy es un excelente proyecto para esto que se integra bien con NumPy. Mire las funciones de autoenlace o lambdify o revise Jensen's blogpost about a similar question.

Los derivados automáticos son muy geniales, no son propensos a errores numéricos, pero requieren algunas bibliotecas adicionales (google para esto, hay algunas buenas opciones). Esta es la elección más robusta pero también la más sofisticada/difícil de configurar. Si está bien restringirse a la sintaxis numpy, entonces Theano podría ser una buena opción.

Aquí hay un ejemplo usando 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

Disculpe, si esto parece estúpido, ¿cuál es la diferencia entre 3.Diferenciación simbólica y 4. ¿Por diferenciación manual? – DrStrangeLove

+8

Cuando dije "diferenciación simbólica", quise dar a entender que el proceso fue manejado por una computadora. En principio, 3 y 4 difieren solo por quién hace el trabajo, la computadora o el programador. 3 es preferible a 4 debido a la consistencia, la escalabilidad y la pereza. 4 es necesario si 3 no puede encontrar una solución. – MRocklin

+1

Muchas gracias! Pero, ¿qué es [2. 2. 2. 2. 2.] en la última línea? – DrStrangeLove

22

NumPy no proporciona funcionalidad general para calcular derivados. Se puede maneja el caso especial de los polinomios simples sin embargo:

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

Si desea calcular la derivada numérica, usted puede conseguir lejos con el uso de cocientes de diferencias centrales para la gran mayoría de las aplicaciones. Para el derivado en un único punto, la fórmula sería algo así como

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

si tiene una matriz x de abscisas con una matriz correspondiente y de valores de función, puede Comput aproximaciones de derivados con

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

'Calcular derivados numéricos para un caso más general es fácil' - Me permito diferir, calcular derivadas numéricas para casos generales es bastante difícil. Usted acaba de elegir funciones bien educadas. –

+0

¿Qué significa 2 después de >>> imprimir p ?? (en la 2da línea) – DrStrangeLove

+0

@DrStrangeLove: Ese es el exponente. Está destinado a simular la notación matemática. –

2

Dependiendo del nivel de precisión que se requiere se puede trabajar por su cuenta, mediante el simple prueba de diferenciación:

>>> (((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 

no podemos tomar el límite del gradiente, pero es un poco divertido. Tienes que tener cuidado, porque aunque

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

La manera más directa de lo que puedo pensar es el uso de numpy's gradient function:

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

De esta manera, dydx se calcula utilizando diferencias Central y del Este tienen la misma longitud que y, a diferencia de numpy.diff, que usa las diferencias hacia delante y devolverá (n-1) vector de tamaño.

+0

¿Qué pasa si dx no es constante? – weberc2

+2

@ weberc2, en ese caso debe dividir un vector por otro, pero trate los bordes por separado con derivados hacia adelante y hacia atrás manualmente. – Sparkler

+1

O puede interpolar y con un dx constante, luego calcule el gradiente. – IceArdor

3

Voy a tirar otro método en el montón ...

scipy.interpolate 's muchas estrías de interpolación son capaces de proporcionar derivados. Por lo tanto, el uso de un spline lineal (k=1), la derivada de la spline (utilizando el método derivative()) debe ser equivalente a una diferencia hacia adelante. No estoy del todo seguro, pero creo que usar un derivado de spline cúbico sería similar a una derivada de diferencia centrada, ya que usa valores de antes y después para construir la spline cúbica.

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

Suponiendo que desea utilizar numpy, puede numéricamente calcular la derivada de una función en cualquier momento utilizando el Rigorous definition:

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

Usted puede también utilizar el Symmetric derivative para obtener mejores resultados:

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

Usando su ejemplo, el código completo debe ser algo como:

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

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

Ahora, puede numéricamente encontrar la derivada en x=5:

In [1]: d_fun(5) 
Out[1]: 9.999999999621423 
Cuestiones relacionadas