例如,如何计算函数的导数
y = x 2 +1
使用numpy
?
假设我想要x = 5时的导数值...
Answers:
您有四个选择
有限的差异不需要外部工具,但容易出现数值误差,如果您处于多变量情况,则可能需要一段时间。
如果您的问题足够简单,则使用符号区分是理想的选择。如今,符号方法变得越来越强大。SymPy是一个出色的项目,可以很好地与NumPy集成。查看autowrap或lambdify函数,或查看Jensen的博客文章,探讨类似问题。
自动导数非常酷,不易出现数字错误,但确实需要一些其他库(为此,google,有一些不错的选择)。这是设置选项中最可靠但也最复杂/最困难的。如果您可以限制自己使用numpy
语法,那么Theano可能是一个不错的选择。
这是使用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
(不确定它们的作用)。
我能想到的最简单的方法是使用numpy的渐变函数:
x = numpy.linspace(0,10,1000)
dx = x[1]-x[0]
y = x**2 + 1
dydx = numpy.gradient(y, dx)
这样,dydx将使用中心差异进行计算,并且与y具有相同的长度,这与numpy.diff不同,后者使用前向差异并返回(n-1)个大小矢量。
dx
要numpy.gradient
代替x
?(ii)我们也可以按如下方式处理您的最后一行dydx = numpy.gradient(y, numpy.gradient(x))
吗?
NumPy不提供用于计算导数的常规功能。但是,它可以处理多项式的简单特殊情况:
>>> p = numpy.poly1d([1, 0, 1])
>>> print p
2
1 x + 1
>>> q = p.deriv()
>>> print q
2 x
>>> q(5)
10
如果要通过数值计算导数,则可以在大多数应用程序中避免使用中心商。对于单点的导数,公式将类似于
x = 5.0
eps = numpy.sqrt(numpy.finfo(float).eps) * (1.0 + x)
print (p(x + eps) - p(x - eps)) / (2.0 * eps * x)
如果您有一个x
横坐标数组和一个对应y
的函数值数组,则可以使用以下公式计算导数的近似值:
numpy.diff(y) / numpy.diff(x)
1 * x**2 + 1
。他们将其2
放在上面的行中,因为它是指数。从远处看。
假设要使用numpy
,可以使用Rigorous定义在任意点上通过数值计算函数的导数 :
def d_fun(x):
h = 1e-5 #in theory h is an infinitesimal
return (fun(x+h)-fun(x))/h
您也可以使用对称导数以获得更好的结果:
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
使用您的示例,完整的代码应类似于:
def fun(x):
return x**2 + 1
def d_fun(x):
h = 1e-5
return (fun(x+h)-fun(x-h))/(2*h)
现在,您可以在以下位置找到数值的导数x=5
:
In [1]: d_fun(5)
Out[1]: 9.999999999621423
我会在堆上扔另一种方法...
scipy.interpolate
的许多内插样条能够提供导数。因此,使用线性样条(k=1
),样条的导数(使用derivative()
方法)应等于正向差。我不确定,但是我相信使用三次样条导数将类似于居中差导数,因为它使用前后的值来构造三次样条。
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)
为了计算梯度,机器学习社区使用Autograd:
“ 有效地计算numpy代码的派生。 ”
安装:
pip install autograd
这是一个例子:
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))
它还可以计算复杂函数(例如多元函数)的梯度。
根据您要求的精度水平,您可以使用简单的区分证明来自己解决:
>>> (((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
我们实际上不能接受渐变的极限,但是有点有趣。你一定要提防,因为
>>> (((5+0.0000000000000001)**2+1)-((5)**2+1))/0.0000000000000001
0.0
您可以使用scipy
,这很简单:
scipy.misc.derivative(func, x0, dx=1.0, n=1, args=(), order=3)
在一个点上找到函数的n阶导数。
在您的情况下:
from scipy.misc import derivative
def f(x):
return x**2 + 1
derivative(f, 5, dx=1e-6)
# 10.00000000139778