Подтвердить что ты не робот

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

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

y = x 2 +1

с помощью numpy?

Скажем, я хочу, чтобы значение производной при x = 5...

4b9b3361

Ответ 1

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

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

Символическое дифференцирование идеально, если ваша проблема достаточно проста. Символические методы в настоящее время становятся довольно устойчивыми. SymPy - отличный проект для этого, который хорошо интегрируется с NumPy. Посмотрите на функции autowrap или lambdify или зайдите в блог Jensen о подобном вопросе.

Автоматические производные очень классные, не подвержены числовым ошибкам, но требуют некоторых дополнительных библиотек (для этого есть несколько хороших вариантов). Это самый надежный, но также самый сложный/сложный выбор. Если вы отлично ограничиваете себя синтаксисом 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.]

Ответ 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)

Ответ 3

Самый простой способ, которым я могу думать, - использовать функцию градиента 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).

Ответ 4

Я поставлю еще один метод на куче...

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

Предполагая, что вы хотите использовать 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

Ответ 6

В зависимости от уровня точности, который вы требуете, вы можете сами это исправить, используя простое доказательство дифференциации:

>>> (((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

Ответ 7

Для расчета градиентов сообщество машинного обучения использует 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))

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