Comment calculer la dérivée d'une fonction, par exemple
y = x 2 +1
en utilisant numpy
?
Disons que je veux la valeur de la dérivée à x = 5 ...
Comment calculer la dérivée d'une fonction, par exemple
y = x 2 +1
en utilisant numpy
?
Disons que je veux la valeur de la dérivée à x = 5 ...
Réponses:
Vous avez quatre options
Les différences finies ne nécessitent aucun outil externe mais sont sujettes à des erreurs numériques et, si vous êtes dans une situation à plusieurs variables, peuvent prendre un certain temps.
La différenciation symbolique est idéale si votre problème est assez simple. Les méthodes symboliques deviennent assez robustes de nos jours. SymPy est un excellent projet pour cela qui s'intègre bien avec NumPy. Regardez les fonctions autowrap ou lambdify ou consultez le blog de Jensen sur une question similaire .
Les dérivés automatiques sont très cool, ne sont pas sujets aux erreurs numériques, mais nécessitent des bibliothèques supplémentaires (google pour cela, il y a quelques bonnes options). C'est le choix le plus robuste mais aussi le plus sophistiqué / difficile à mettre en place. Si vous vous limitez à la numpy
syntaxe, Theano pourrait être un bon choix.
Voici un exemple utilisant 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
(pas sûr cependant de ce qu'ils font exactement).
Le moyen le plus simple auquel je puisse penser est d'utiliser la fonction de dégradé de numpy :
x = numpy.linspace(0,10,1000)
dx = x[1]-x[0]
y = x**2 + 1
dydx = numpy.gradient(y, dx)
De cette façon, dydx sera calculé en utilisant des différences centrales et aura la même longueur que y, contrairement à numpy.diff, qui utilise des différences avant et retournera un vecteur de taille (n-1).
dx
au numpy.gradient
lieu de x
? (ii) Pouvons-nous également faire la dernière ligne de la vôtre comme suit dydx = numpy.gradient(y, numpy.gradient(x))
:?
NumPy ne fournit pas de fonctionnalités générales pour calculer les dérivés. Cependant, il peut gérer le cas particulier simple des polynômes:
>>> p = numpy.poly1d([1, 0, 1])
>>> print p
2
1 x + 1
>>> q = p.deriv()
>>> print q
2 x
>>> q(5)
10
Si vous souhaitez calculer la dérivée numériquement, vous pouvez utiliser les quotients de différence centrale pour la grande majorité des applications. Pour le dérivé en un seul point, la formule serait quelque chose comme
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 vous avez un tableau x
d'abscisses avec un tableau correspondant y
de valeurs de fonction, vous pouvez calculer des approximations de dérivées avec
numpy.diff(y) / numpy.diff(x)
1 * x**2 + 1
. Ils mettent le 2
dans la ligne ci-dessus parce que c'est un exposant. Regardez-le de loin.
En supposant que vous souhaitiez utiliser numpy
, vous pouvez calculer numériquement la dérivée d'une fonction à tout moment en utilisant la définition rigoureuse :
def d_fun(x):
h = 1e-5 #in theory h is an infinitesimal
return (fun(x+h)-fun(x))/h
Vous pouvez également utiliser le dérivé symétrique pour de meilleurs résultats:
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
En utilisant votre exemple, le code complet devrait ressembler à quelque chose comme:
def fun(x):
return x**2 + 1
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
Maintenant, vous pouvez trouver numériquement la dérivée à x=5
:
In [1]: d_fun(5)
Out[1]: 9.999999999621423
Je vais jeter une autre méthode sur la pile ...
scipy.interpolate
De nombreuses splines interpolantes sont capables de fournir des dérivés. Ainsi, en utilisant une spline linéaire ( k=1
), la dérivée de la spline (en utilisant la derivative()
méthode) devrait être équivalente à une différence directe. Je ne suis pas tout à fait sûr, mais je pense que l'utilisation d'un dérivé de spline cubique serait similaire à une dérivée de différence centrée car elle utilise des valeurs d'avant et d'après pour construire la spline cubique.
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)
Pour calculer les dégradés, la communauté d'apprentissage automatique utilise Autograd:
À installer:
pip install autograd
Voici un exemple:
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))
Il peut également calculer des gradients de fonctions complexes, par exemple des fonctions multivariées.
Selon le niveau de précision dont vous avez besoin, vous pouvez le déterminer vous-même, en utilisant la simple preuve de différenciation:
>>> (((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
nous ne pouvons pas vraiment prendre la limite du gradient, mais c'est plutôt amusant. Tu dois faire attention parce que
>>> (((5+0.0000000000000001)**2+1)-((5)**2+1))/0.0000000000000001
0.0
Vous pouvez utiliser scipy
, ce qui est assez simple:
scipy.misc.derivative(func, x0, dx=1.0, n=1, args=(), order=3)
Trouvez la nième dérivée d'une fonction en un point.
Dans ton cas:
from scipy.misc import derivative
def f(x):
return x**2 + 1
derivative(f, 5, dx=1e-6)
# 10.00000000139778