numpy.gradient#

numpy.gradient(f, *varargs, axis=None, edge_order=1)[source]#

傳回 N 維陣列的梯度。

梯度是使用內部點的二階精確中心差分,以及邊界處的一階或二階精確單邊(前向或後向)差分計算的。因此,傳回的梯度與輸入陣列具有相同的形狀。

參數:
f類陣列

包含純量函數樣本的 N 維陣列。

varargs純量或陣列列表,選用

f 值之間的間距。所有維度的預設單位間距。間距可以使用以下方式指定

  1. 單一純量以指定所有維度的樣本距離。

  2. N 個純量以指定每個維度的常數樣本距離。例如 dxdydz、…

  3. N 個陣列以指定 F 沿每個維度的值的座標。陣列的長度必須符合對應維度的大小

  4. N 個純量/陣列的任意組合,含義如 2. 和 3.

如果給定 axis,varargs 的數量必須等於軸的數量。預設值:1。(請參閱以下範例)。

edge_order{1, 2},選用

梯度是使用邊界處的 N 階精確差分計算的。預設值:1。

axisNone 或 int 或 int 元組,選用

梯度僅沿給定的軸或軸計算。預設值 (axis = None) 是計算輸入陣列所有軸的梯度。軸可以是負數,在這種情況下,它從最後一個軸數到第一個軸。

傳回值:
gradientndarray 或 ndarray 元組

一個 ndarray 元組(或如果只有一個維度,則為單個 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)。紐約:Springer。

[2]

Durran D. R. (1999) Numerical Methods for Wave Equations in Geophysical Fluid Dynamics。紐約: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.])

axis 關鍵字可用於指定要計算梯度的軸的子集

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

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.]]))