dask.array.gradient

dask.array.gradient

dask.array.gradient(f, *varargs, axis=None, **kwargs)[源代码]

返回一个 N 维数组的梯度。

此文档字符串是从 numpy.gradient 复制的。

Dask 版本可能存在一些不一致性。

梯度是使用在内部点上的二阶精确中心差分计算的,并且在边界处使用一阶或二阶精确的一侧(前向或后向)差分。因此,返回的梯度与输入数组具有相同的形状。

参数
farray_like

一个包含标量函数样本的N维数组。

varargs标量或数组的列表,可选

f 值之间的间距。所有维度的默认单位间距。可以使用以下方式指定间距:

  1. 单个标量以指定所有维度的采样距离。

  2. N 个标量用于指定每个维度的恒定采样距离。例如 dx, dy, dz, …

  3. N 个数组用于指定沿 F 的每个维度的值的坐标。数组的长度必须与相应维度的大小匹配。

  4. 任何具有2和3意义的N个标量/数组的组合

如果给出了 axis,则 varargs 的数量必须等于轴的数量。默认值:1。(见下文示例)。

edge_order{1, 2}, 可选 (Dask 中不支持)

梯度是使用边界处的 N 阶精确差分计算的。默认值:1。

1.9.1 新版功能.

None 或 int 或 int 的元组,可选

梯度仅沿给定的轴或轴计算。默认(axis = None)是计算输入数组所有轴的梯度。轴可以是负数,在这种情况下,它从最后一个轴计数到第一个轴。

1.11.0 新版功能.

返回
梯度ndarray 或 ndarray 的元组

一个 ndarrays 的元组(如果只有一个维度,则为单个 ndarray),对应于 f 对每个维度的导数。每个导数与 f 具有相同的形状。

注释

假设 \(f\in C^{3}\) 至少有3阶连续导数),并设 \(h_{*}\) 为非均匀步长,我们最小化“一致性误差” \(\eta_{i}\),该误差是真实梯度与其从相邻网格点线性组合估计值之间的差异:

\[\begin{split}\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]\end{split}\]

通过将 \(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) 数值数学 (应用数学文本)。纽约: Springer.

2

Durran D. R. (1999) 《地球物理流体动力学中的波动方程数值方法》。纽约:Springer。

3

Fornberg B. (1988) 在任意间隔网格上生成有限差分公式的生成,《计算数学》51卷,第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.]]))