¿Cómo calculo la derivada de una función, por ejemplo?
y = x 2 +1
usando numpy
?
Digamos, quiero el valor de la derivada en x = 5 ...
¿Cómo calculo la derivada de una función, por ejemplo?
y = x 2 +1
usando numpy
?
Digamos, quiero el valor de la derivada en x = 5 ...
Respuestas:
Tienes cuatro opciones
Las diferencias finitas no requieren herramientas externas, pero son propensas a errores numéricos y, si se encuentra en una situación multivariante, 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 proyecto excelente para esto que se integra bien con NumPy. Mire las funciones autowrap o lambdify o consulte la publicación de blog de Jensen sobre una pregunta similar .
Los derivados automáticos son muy interesantes, no son propensos a errores numéricos, pero requieren algunas bibliotecas adicionales (google para esto, hay algunas buenas opciones). Esta es la opción más robusta pero también la más sofisticada / difícil de configurar. Si está bien restringiéndose a la numpy
sintaxis, 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.]
mpmath
(sin embargo, no estoy seguro de qué hacen exactamente).
La forma más sencilla que se me ocurre es usar la función de gradiente de numpy :
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 calculará usando diferencias centrales y tendrá la misma longitud que y, a diferencia de numpy.diff, que usa diferencias hacia adelante y devolverá (n-1) el tamaño del vector.
dx
a en numpy.gradient
lugar de x
? (ii) ¿Podemos también hacer la última línea tuya de la siguiente manera dydx = numpy.gradient(y, numpy.gradient(x))
:?
NumPy no proporciona funcionalidad general para calcular derivadas. Sin embargo, puede manejar el caso especial simple de polinomios:
>>> 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éricamente, puede utilizar cocientes de diferencia central para la gran mayoría de aplicaciones. Para la derivada en un solo punto, la fórmula sería algo 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 calcular aproximaciones de derivadas con
numpy.diff(y) / numpy.diff(x)
1 * x**2 + 1
. Pusieron el 2
en la línea de arriba porque es un exponente. Míralo desde la distancia.
Suponiendo que quiera usar numpy
, puede calcular numéricamente la derivada de una función en cualquier punto usando la definición rigurosa :
def d_fun(x):
h = 1e-5 #in theory h is an infinitesimal
return (fun(x+h)-fun(x))/h
También puede utilizar la derivada simétrica 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 debería verse así:
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 encontrar numéricamente la derivada en x=5
:
In [1]: d_fun(5)
Out[1]: 9.999999999621423
Lanzaré otro método a la pila ...
scipy.interpolate
Los numerosos splines de interpolación son capaces de proporcionar derivados. Entonces, usando una spline lineal ( k=1
), la derivada de la spline (usando el derivative()
método) debería ser equivalente a una diferencia hacia adelante. No estoy del todo seguro, pero creo que usar una derivada de spline cúbica 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)
Para calcular gradientes, la comunidad de aprendizaje automático usa Autograd:
" Calcula de manera eficiente las derivadas de numerosos códigos " .
Instalar:
pip install autograd
Aquí hay un ejemplo:
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))
También puede calcular gradientes de funciones complejas, por ejemplo, funciones multivariadas.
Dependiendo del nivel de precisión que requiera, puede resolverlo usted mismo, utilizando la sencilla 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
en realidad no podemos tomar el límite del gradiente, pero es un poco divertido. Debes tener cuidado porque
>>> (((5+0.0000000000000001)**2+1)-((5)**2+1))/0.0000000000000001
0.0
Puede usar scipy
, que es bastante sencillo:
scipy.misc.derivative(func, x0, dx=1.0, n=1, args=(), order=3)
Encuentra la enésima derivada de una función en un punto.
En tu caso:
from scipy.misc import derivative
def f(x):
return x**2 + 1
derivative(f, 5, dx=1e-6)
# 10.00000000139778