numpy.gradient#
- numpy.градиент(f, *varargs, ось=None, edge_order=1)[источник]#
Возвращает градиент N-мерного массива.
Градиент вычисляется с использованием центральных разностей второго порядка точности во внутренних точках и односторонних разностей первого или второго порядка точности (вперёд или назад) на границах. Возвращаемый градиент, следовательно, имеет ту же форму, что и входной массив.
- Параметры:
- farray_like
N-мерный массив, содержащий выборки скалярной функции.
- varargsсписок скаляров или массивов, необязательно
Расстояние между значениями f. По умолчанию единичное расстояние для всех измерений. Расстояние можно указать с помощью:
один скаляр для указания расстояния выборки для всех измерений.
N скаляров для указания постоянного расстояния выборки для каждого измерения. Т.е. dx, dy, dz, …
N массивов для указания координат значений вдоль каждого измерения F. Длина массива должна соответствовать размеру соответствующего измерения
Любая комбинация 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 аргумент определяет интервал между точками выборки во входном массиве. Он может принимать две формы:
Массив, задающий координаты, которые могут быть неравномерно распределены:
>>> x = np.array([0., 2., 3., 6., 8.]) >>> y = x ** 2 >>> np.gradient(y, x, edge_order=2) array([ 0., 4., 6., 12., 16.])
Скаляр, представляющий фиксированное расстояние между выборками:
>>> 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.]]))