Как вычислить производную с помощью Numpy?



Как вычислить производную функции, например




y = x2+1




С помощью numpy?



допустим, я хочу значение производной при x = 5...

2567   7  

7 ответов:

у вас есть четыре варианта

  1. можно использовать Конечных Разностей
  2. можно использовать Автоматическая Производные
  3. можно использовать Символическая Дифференциация
  4. вы можете вычислить производные вручную.

конечные разности не требуют внешних инструментов, но склонны к численной ошибке и, если вы находитесь в многомерной ситуации, может занять некоторое время.

символические дифференциация идеальна, если ваша задача достаточно проста. Символические методы становятся довольно надежными в эти дни. 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:

"эффективно вычисляет производные кода 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))

Он также может вычислять градиенты сложных функций, например, многомерных функций.

Comments

    Ничего не найдено.