我试图用数值计算numpy中数组的二阶梯度。
a = np.sin(np.arange(0, 10, .01))
da = np.gradient(a)
dda = np.gradient(da)
这就是我想出来的。这是应该做的吗?
我问这个是因为在numpy中没有一个选项说np.gradient(a,order=2)。我担心这个用法是否是错误的,这就是为什么numpy没有实现这个。
PS1:我确实知道有np.diff(a,2),但这只是单边估计,所以我很好奇为什么np.gradient没有类似的关键字。
PS2:np.sin()是一个玩具数据--真实的的数据没有分析形式。
谢谢你,谢谢你
6条答案
按热度按时间iq3niunx1#
我支持jrennie的第一句话--这要看情况而定。numpy.gradient函数要求数据均匀分布(尽管多维时允许每个方向上的距离不同)。如果您的数据不符合这一点,那么numpy.gradient就没有多大用处。实验数据可能(好的,会有)噪声,此外,不一定是所有均匀的间隔。在这种情况下,它可能是更好的使用scipy之一。插值样条函数(或对象)。这些函数可以采用不均匀间隔的数据,允许平滑,并且可以返回最大为k-1的导数,其中k是所请求的样条拟合的阶数。k的默认值为3,因此二阶导数就足够了。例如:
面向对象的样条函数,如scipy.interpolate.UnivariateSpline,有导数的方法。注意导数方法在Scipy 0.13中实现,在0.12中没有。
请注意,正如@JosephCottham在2018年的评论中所指出的,这个答案(至少对Numpy 1.08有效),从(至少)Numpy 1.14开始就不再适用了。
wd2eg0qa2#
数值梯度计算没有一个通用的正确答案,在计算样本数据的梯度之前,您必须对生成该数据的底层函数做一些假设。从技术上讲,您可以使用
np.diff
进行梯度计算。使用np.gradient
是一种合理的方法。我看不出您所做的有什么根本性的错误---它'这是一维函数的二阶导数的一种特殊近似。uelo1irk3#
由于梯度函数考虑了向左和向右的一个数据点,因此在多次应用时,这种情况会继续/扩散。
另一方面,二阶导数可通过以下公式计算:
比较here。这具有仅考虑两个相邻像素的优点。
在图中,双np.gradient方法(左)和上述公式(右)(由np.diff实现)进行了比较。由于f(x)在零点只有一个扭结,二阶导数(绿色)应该只有一个峰值。由于双梯度解决方案在每个方向上考虑了2个相邻点,这导致在+/- 1处有有限的二阶导数值。
我不知道为什么会有
np.gradient
和np.diff
,但原因可能是,np.gradient的第二个参数定义了像素距离(对于每个维度),对于图像,它可以同时应用于两个维度gy, gx = np.gradient(a)
。代码
ogq8wdun4#
当我不断地以一种形式或另一种形式一次又一次地解决这个问题时,我决定写一个函数
gradient_n
,它给np.gradient
增加了一个微分或功能。不是所有的np.gradient功能都被支持,比如多轴微分。与
np.gradient
类似,gradient_n
返回与输入相同形状的微分结果。此外,它还支持像素距离参数(d
)。pftdvrlh5#
这是从原始文档中摘录的内容(在撰写本文时,可在http://docs.scipy.org/doc/numpy/reference/generated/numpy.gradient.html中找到)。它指出,除非采样距离为1,否则需要包含一个包含距离的列表作为参数。
返回N维数组的渐变。
梯度是使用内部的二阶精确中心差和边界处的一阶差或二阶精确单侧(向前或向后)差计算的。因此,返回的梯度具有与输入数组相同的形状。
参数:
f:array_like包含标量函数样本的N维数组。
varargs:标量列表,可选的N个标量,指定每个维度的采样距离,即dx、dy、dz...默认距离:1.
边顺序:{1,2},使用边界处的N阶精度差计算可选梯度。默认值:1. 1.9.1版中的新增功能。
退货:
gradient:ndarray与f形状相同的N个数组,给出f在每个维度上的导数。
b4qexyjb6#
我的解决方案是创建一个类似于
np.gradient
的函数,该函数从数组数据中计算二阶导数。以您的示例为例,