numpy.gradient#

numpy.градиент(f, *varargs, ось=None, edge_order=1)[источник]#

Возвращает градиент N-мерного массива.

Градиент вычисляется с использованием центральных разностей второго порядка точности во внутренних точках и односторонних разностей первого или второго порядка точности (вперёд или назад) на границах. Возвращаемый градиент, следовательно, имеет ту же форму, что и входной массив.

Параметры:
farray_like

N-мерный массив, содержащий выборки скалярной функции.

varargsсписок скаляров или массивов, необязательно

Расстояние между значениями f. По умолчанию единичное расстояние для всех измерений. Расстояние можно указать с помощью:

  1. один скаляр для указания расстояния выборки для всех измерений.

  2. N скаляров для указания постоянного расстояния выборки для каждого измерения. Т.е. dx, dy, dz, …

  3. N массивов для указания координат значений вдоль каждого измерения F. Длина массива должна соответствовать размеру соответствующего измерения

  4. Любая комбинация N скаляров/массивов со значением 2. и 3.

Если ось Если задано, количество переменных аргументов должно равняться количеству осей, указанных в параметре axis. По умолчанию: 1. (см. примеры ниже).

edge_order{1, 2}, необязательно

Градиент вычисляется с использованием разностей N-го порядка точности на границах. По умолчанию: 1.

осьNone или int или кортеж ints, опционально

Градиент вычисляется только вдоль заданной оси или осей. По умолчанию (axis = None) градиент вычисляется для всех осей входного массива. axis может быть отрицательным, в этом случае отсчёт ведётся от последней к первой оси.

Возвращает:
градиентndarray или кортеж из ndarray

Кортеж ndarrays (или одиночный ndarray, если есть только одно измерение), соответствующий производным f по каждому измерению. Каждая производная имеет ту же форму, что и f.

Примечания

Предполагая, что \(f\in C^{3}\) (т.е., \(f\) имеет по крайней мере 3 непрерывные производные) и пусть \(h_{*}\) быть неоднородным шагом, мы минимизируем 'ошибку согласованности' \(\eta_{i}\) между истинным градиентом и его оценкой из линейной комбинации соседних точек сетки:

\[\eta_{i} = f_{i}^{\left(1\right)} - \left[ \alpha f\left(x_{i}\right) + \beta f\left(x_{i} + h_{d}\right) + \gamma f\left(x_{i}-h_{s}\right) \right]\]

Путем подстановки \(f(x_{i} + h_{d})\) и \(f(x_{i} - h_{s})\) с их разложением в ряд Тейлора, это сводится к решению следующей линейной системы:

\[\begin{split}\left\{ \begin{array}{r} \alpha+\beta+\gamma=0 \\ \beta h_{d}-\gamma h_{s}=1 \\ \beta h_{d}^{2}+\gamma h_{s}^{2}=0 \end{array} \right.\end{split}\]

Полученное приближение \(f_{i}^{(1)}\) следующий:

\[\hat f_{i}^{(1)} = \frac{ h_{s}^{2}f\left(x_{i} + h_{d}\right) + \left(h_{d}^{2} - h_{s}^{2}\right)f\left(x_{i}\right) - h_{d}^{2}f\left(x_{i}-h_{s}\right)} { h_{s}h_{d}\left(h_{d} + h_{s}\right)} + \mathcal{O}\left(\frac{h_{d}h_{s}^{2} + h_{s}h_{d}^{2}}{h_{d} + h_{s}}\right)\]

Стоит отметить, что если \(h_{s}=h_{d}\) (т.е., данные равномерно распределены) мы находим стандартное приближение второго порядка:

\[\hat f_{i}^{(1)}= \frac{f\left(x_{i+1}\right) - f\left(x_{i-1}\right)}{2h} + \mathcal{O}\left(h^{2}\right)\]

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

Ссылки

[1]

Quarteroni A., Sacco R., Saleri F. (2007) Numerical Mathematics (Texts in Applied Mathematics). New York: Springer.

[2]

Durran D. R. (1999) Numerical Methods for Wave Equations in Geophysical Fluid Dynamics. New York: Springer.

[3]

Fornberg B. (1988) Generation of Finite Difference Formulas on Arbitrarily Spaced Grids, Mathematics of Computation 51, no. 184 : 699-706. PDF.

Примеры

>>> import numpy as np
>>> f = np.array([1, 2, 4, 7, 11, 16])
>>> np.gradient(f)
array([1. , 1.5, 2.5, 3.5, 4.5, 5. ])
>>> np.gradient(f, 2)
array([0.5 ,  0.75,  1.25,  1.75,  2.25,  2.5 ])

Интервал также может быть указан с помощью массива, представляющего координаты значений F по измерениям. Например, равномерный интервал:

>>> x = np.arange(f.size)
>>> np.gradient(f, x)
array([1. ,  1.5,  2.5,  3.5,  4.5,  5. ])

Или неоднородный:

>>> x = np.array([0., 1., 1.5, 3.5, 4., 6.])
>>> np.gradient(f, x)
array([1. ,  3. ,  3.5,  6.7,  6.9,  2.5])

Для двумерных массивов возвращаются два массива, упорядоченные по осям. В этом примере первый массив представляет градиент по строкам, а второй — по столбцам:

>>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]]))
(array([[ 2.,  2., -1.],
        [ 2.,  2., -1.]]),
 array([[1. , 2.5, 4. ],
        [1. , 1. , 1. ]]))

В этом примере также указан интервал: равномерный для axis=0 и неравномерный для axis=1

>>> dx = 2.
>>> y = [1., 1.5, 3.5]
>>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]]), dx, y)
(array([[ 1. ,  1. , -0.5],
        [ 1. ,  1. , -0.5]]),
 array([[2. , 2. , 2. ],
        [2. , 1.7, 0.5]]))

Можно указать, как обрабатываются границы, используя edge_order

>>> x = np.array([0, 1, 2, 3, 4])
>>> f = x**2
>>> np.gradient(f, edge_order=1)
array([1.,  2.,  4.,  6.,  7.])
>>> np.gradient(f, edge_order=2)
array([0., 2., 4., 6., 8.])

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

>>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]]), axis=0)
array([[ 2.,  2., -1.],
       [ 2.,  2., -1.]])

The varargs аргумент определяет интервал между точками выборки во входном массиве. Он может принимать две формы:

  1. Массив, задающий координаты, которые могут быть неравномерно распределены:

>>> x = np.array([0., 2., 3., 6., 8.])
>>> y = x ** 2
>>> np.gradient(y, x, edge_order=2)
array([ 0.,  4.,  6., 12., 16.])
  1. Скаляр, представляющий фиксированное расстояние между выборками:

>>> dx = 2
>>> x = np.array([0., 2., 4., 6., 8.])
>>> y = x ** 2
>>> np.gradient(y, dx, edge_order=2)
array([ 0.,  4.,  8., 12., 16.])

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

>>> dx = 2
>>> dy = 3
>>> x = np.arange(0, 6, dx)
>>> y = np.arange(0, 9, dy)
>>> xs, ys = np.meshgrid(x, y)
>>> zs = xs + 2 * ys
>>> np.gradient(zs, dy, dx)  # Passing two scalars
(array([[2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]]),
 array([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]]))

Разрешено также смешивать скаляры и массивы:

>>> np.gradient(zs, y, dx)  # Passing one array and one scalar
(array([[2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]]),
 array([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]]))