Necesita usar Sympy: sympy.org/en/index.html Numpy es una biblioteca de cálculo numérico para Python
prrao
Alternativamente, ¿desea un método para estimar el valor numérico de la derivada? Para ello, puede utilizar un método de diferencias finitas, pero tenga en cuenta que suelen ser terriblemente ruidosos.
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 numpysintaxis, 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.]
Lo siento, si esto parece una estupidez, ¿Cuáles son las diferencias entre la diferenciación simbólica y la diferenciación manual?
DrStrangeLove
11
Cuando dije "diferenciación simbólica", quise dar a entender que el proceso fue manejado por una computadora. En principio, el 3 y el 4 se diferencian únicamente por quién hace el trabajo, la computadora o el programador. Se prefiere 3 sobre 4 debido a la consistencia, escalabilidad y pereza. 4 es necesario si 3 no logra encontrar una solución.
MRocklin
4
En la línea 7 hicimos f, una función que calcula la derivada de y wrt x. En 8 aplicamos esta función derivada a un vector de todos unos y obtenemos el vector de todos los dos. Esto se debe a que, como se indica en la línea 6, yprime = 2 * x.
MRocklin
En aras de la completitud, también puede hacer la diferenciación por integración (consulte la fórmula integral de Cauchy), se implementa, por ejemplo, en mpmath(sin embargo, no estoy seguro de qué hacen exactamente).
DerWeh
¿Existe una manera fácil de hacer diferencias finitas en numpy sin implementarlo usted mismo? por ejemplo, quiero encontrar el gradiente de una función en puntos predefinidos.
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.
@ weberc2, en ese caso debe dividir un vector por otro, pero tratar los bordes por separado con derivadas hacia adelante y hacia atrás manualmente.
Sparkler
2
O puede interpolar y con una constante dx, luego calcular el gradiente.
IceArdor
@Sparkler Gracias por tu sugerencia. Si puedo hacer 2 pequeñas preguntas, (i) ¿por qué pasamos dxa en numpy.gradientlugar de x? (ii) ¿Podemos también hacer la última línea tuya de la siguiente manera dydx = numpy.gradient(y, numpy.gradient(x)):?
user929304
2
A partir de v1.13, se puede especificar un espaciado no uniforme utilizando una matriz como segundo argumento. Vea la sección de Ejemplos de esta página .
Nathaniel Jones
28
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
21 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
"Calcular derivadas numéricas para casos más generales es fácil". Lamento diferir, calcular derivadas numéricas para casos generales es bastante difícil. Simplemente eligió funciones con buen comportamiento.
High Performance Mark
¿Qué significa 2 después de >>> imprimir p ?? (en la segunda línea)
DrStrangeLove
@DrStrangeLove: Ese es el exponente. Está destinado a simular la notación matemática.
Sven Marnach
@SvenMarnach es su máximo exponente ?? ¿¿o que?? ¿Por qué cree que el exponente es 2? Ingresamos solo coeficientes ...
DrStrangeLove
2
@DrStrangeLove: se supone que la salida debe leerse como 1 * x**2 + 1. Pusieron el 2en la línea de arriba porque es un exponente. Míralo desde la distancia.
Sven Marnach
15
Suponiendo que quiera usar numpy, puede calcular numéricamente la derivada de una función en cualquier punto usando la definición rigurosa :
defd_fun(x):
h = 1e-5#in theory h is an infinitesimalreturn (fun(x+h)-fun(x))/h
También puede utilizar la derivada simétrica para obtener mejores resultados:
defd_fun(x):
h = 1e-5return (fun(x+h)-fun(x-h))/(2*h)
Usando su ejemplo, el código completo debería verse así:
deffun(x):return x**2 + 1defd_fun(x):
h = 1e-5return (fun(x+h)-fun(x-h))/(2*h)
Ahora, puede encontrar numéricamente la derivada en x=5:
scipy.interpolateLos 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)
acabo de intentar esto, sigo recibiendo errores de esta función AxisError: el eje -1 está fuera de los límites para la matriz de dimensión 0 y tampoco veo ninguna respuesta a esto en la comunidad, ¿alguna ayuda?
Ayan Mitra
Publique su problema como una nueva pregunta y vincúlelo aquí. Probablemente sea necesario proporcionar un ejemplo que provoque su error. Los errores que tengo con las funciones de interp suelen deberse a que los datos no están bien formados al entrar, como valores repetidos, número incorrecto de dimensiones, una de las matrices está vacía accidentalmente, los datos no se ordenan según xo cuando se ordenan no es un función válida, etc. Es posible que scipy esté llamando a numpy incorrectamente, pero es muy poco probable. Compruebe la forma x y la forma y. Vea si np.interp () funciona; de lo contrario, puede proporcionar un error más útil.
flutefreak7
6
Para calcular gradientes, la comunidad de aprendizaje automático usa Autograd:
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.]
fuente
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.
fuente
dx
a ennumpy.gradient
lugar dex
? (ii) ¿Podemos también hacer la última línea tuya de la siguiente maneradydx = 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 correspondientey
de valores de función, puede calcular aproximaciones de derivadas confuente
1 * x**2 + 1
. Pusieron el2
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
fuente
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 elderivative()
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)
fuente
Para calcular gradientes, la comunidad de aprendizaje automático usa Autograd:
Instalar:
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.
fuente
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
fuente
Puede usar
scipy
, que es bastante sencillo:scipy.misc.derivative(func, x0, dx=1.0, n=1, args=(), order=3)
En tu caso:
from scipy.misc import derivative def f(x): return x**2 + 1 derivative(f, 5, dx=1e-6) # 10.00000000139778
fuente