7 ответов:
у вас есть четыре варианта
- можно использовать Конечных Разностей
- можно использовать Автоматическая Производные
- можно использовать Символическая Дифференциация
- вы можете вычислить производные вручную.
конечные разности не требуют внешних инструментов, но склонны к численной ошибке и, если вы находитесь в многомерной ситуации, может занять некоторое время.
символические дифференциация идеальна, если ваша задача достаточно проста. Символические методы становятся довольно надежными в эти дни. SymPy это отличный проект для этого, который хорошо интегрируется с NumPy. Посмотрите на функции autowrap или lambdify или проверьте блог Дженсена о подобном вопросе.
автоматические производные очень круты, не склонны к числовым ошибкам, но требуют некоторых дополнительных библиотек (google для этого есть несколько хороших вариантов). Это самый надежный, но и самый сложный/сложный в настройке выбор. Если вы в порядке, ограничивая себя
numpyсинтаксис тут Феано может быть хорошим выбором.вот пример использования 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.]
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)
самый прямой способ, который я могу придумать, это использовать градиентная функция 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) вектор размера.
если вы хотите использовать
numpyможно численно вычислить производную функции в любой точке с помощью строгое определение: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)
в зависимости от уровня точности вы требуете, вы можете решить это самостоятельно, используя простое доказательство дифференциации:
>>> (((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
для вычисления градиентов сообщество машинного обучения использует Autograd:
установка:
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))Он также может вычислять градиенты сложных функций, например, многомерных функций.
Comments