numpy.gradient#
- numpy.gradient(f, *varargs, axis=None, edge_order=1)[源代码]#
返回N维数组的梯度.
梯度使用内部点的二阶精确中心差分以及边界处的一阶或二阶精确单侧(向前或向后)差分计算.因此,返回的梯度与输入数组具有相同的形状.
- 参数:
- farray_like
包含标量函数样本的N维数组.
- varargs标量或数组的列表,可选
f 值之间的间距.所有维度的默认单位间距.可以使用以下方式指定间距:
单个标量,用于指定所有维度的样本距离.
N 个标量,用于指定每个维度的恒定样本距离.即 dx , dy , dz ,…
N 个数组,用于指定 F 沿每个维度的值的坐标.数组的长度必须与相应维度的大小匹配
N 个标量/数组的任意组合,含义同 2 和 3.
如果给出了 axis ,则 varargs 的数量必须等于 axis 参数中指定的轴数.默认值:1.(参见下面的示例).
- edge_order{1, 2}, optional
梯度使用边界处的 N 阶精确差分计算.默认值:1.
- axisNone 或 int 或 int 元组,可选
仅沿给定的轴或多个轴计算梯度.默认值 (axis = None) 是计算输入数组所有轴的梯度.axis 可以为负数,在这种情况下,它从最后一个轴计数到第一个轴.
- 返回:
- 梯度ndarray 或 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). 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.])
axis 关键字可用于指定计算梯度的轴的子集
>>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]]), axis=0) array([[ 2., 2., -1.], [ 2., 2., -1.]])
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.]]))