Python 一维数组的numpy二阶导数
我有一组模拟数据,我想找到n维中的最低斜率。数据的间距在每个维度上都是恒定的,但并不完全相同(为了简单起见,我可以改变这种间距) 我可以忍受一些数值上的不准确,尤其是边缘。我非常不希望生成样条曲线并使用该导数;仅仅依靠原始值就足够了 使用Python 一维数组的numpy二阶导数,python,numpy,Python,Numpy,我有一组模拟数据,我想找到n维中的最低斜率。数据的间距在每个维度上都是恒定的,但并不完全相同(为了简单起见,我可以改变这种间距) 我可以忍受一些数值上的不准确,尤其是边缘。我非常不希望生成样条曲线并使用该导数;仅仅依靠原始值就足够了 使用numpy.gradient()函数,可以用numpy计算一阶导数 import numpy as np data = np.random.rand(30,50,40,20) first_derivative = np.gradient(data) # sec
numpy.gradient()
函数,可以用numpy
计算一阶导数
import numpy as np
data = np.random.rand(30,50,40,20)
first_derivative = np.gradient(data)
# second_derivative = ??? <--- there be kudos (:
色标表示函数值,箭头表示一阶导数(梯度),红点表示最接近零的点,红线表示阈值
< >数据的生成器函数为<代码>(1-NP,Exp(-10×X** 2 - y* 2))/100 < /代码>,席席,Yi生成,代码< NP.MeHGrase< /C> >
拉普拉斯:
黑森:
二阶导数由下式给出。这是一个针对ND数组的Python实现,它包括两次应用
np.gradient
,并适当地存储输出
import numpy as np
def hessian(x):
"""
Calculate the hessian matrix with finite differences
Parameters:
- x : ndarray
Returns:
an array of shape (x.dim, x.ndim) + x.shape
where the array[i, j, ...] corresponds to the second derivative x_ij
"""
x_grad = np.gradient(x)
hessian = np.empty((x.ndim, x.ndim) + x.shape, dtype=x.dtype)
for k, grad_k in enumerate(x_grad):
# iterate over dimensions
# apply gradient again to every component of the first derivative.
tmp_grad = np.gradient(grad_k)
for l, grad_kl in enumerate(tmp_grad):
hessian[k, l, :, :] = grad_kl
return hessian
x = np.random.randn(100, 100, 100)
hessian(x)
请注意,如果您只对二阶导数的大小感兴趣,可以使用实现的,即Hessian矩阵的轨迹(对角线元素之和)
取Hessian矩阵的最小元素可用于估计任何空间方向上的最低坡度 您可以将Hessian矩阵视为gradient of gradient,第二次为第一个gradient的每个组件应用gradient,这里计算的是wikipedia定义的Hessian矩阵,您可以清楚地看到这是gradient of gradient,这里是定义gradient然后Hessian的python实现:
import numpy as np
#Gradient Function
def gradient_f(x, f):
assert (x.shape[0] >= x.shape[1]), "the vector should be a column vector"
x = x.astype(float)
N = x.shape[0]
gradient = []
for i in range(N):
eps = abs(x[i]) * np.finfo(np.float32).eps
xx0 = 1. * x[i]
f0 = f(x)
x[i] = x[i] + eps
f1 = f(x)
gradient.append(np.asscalar(np.array([f1 - f0]))/eps)
x[i] = xx0
return np.array(gradient).reshape(x.shape)
#Hessian Matrix
def hessian (x, the_func):
N = x.shape[0]
hessian = np.zeros((N,N))
gd_0 = gradient_f( x, the_func)
eps = np.linalg.norm(gd_0) * np.finfo(np.float32).eps
for i in range(N):
xx0 = 1.*x[i]
x[i] = xx0 + eps
gd_1 = gradient_f(x, the_func)
hessian[:,i] = ((gd_1 - gd_0)/eps).reshape(x.shape[0])
x[i] =xx0
return hessian
作为检验,(x^2+y^2)的Hessian矩阵是2*I_2,其中I_2是维度2的单位矩阵,Hessian和Laplacian是相关的,但是3个不同的东西。
从2d开始:2个变量的函数(x,y),例如一系列山丘的高度图
- 坡度是方向向量,每个点的方向和长度
xy
这可以由笛卡尔坐标系中的2个数字
给出, 或极坐标中的角度θ和长度dx-dy
。 在一整片山丘上,我们可以看到sqrt(dx^2+dy^2)
- 黑森人描述了x y附近的曲率,例如抛物面或鞍形,
有4个数字:
dxx-dxy-dyx-dyy
- 拉普拉斯算子是1个数,
,在每个点dxx+dyy
。 越过一系列的小山,我们得到了一个 . (功能或功能) (特别光滑。)xy
xy
附近的微小步骤h
,斜率为线性拟合和Hessian二次拟合:
f(xy + h) ~ f(xy)
+ slope . h -- dot product, linear in both slope and h
+ h' H h / 2 -- quadratic in h
这里的xy
,slope
和h
是两个数字的向量,
而H
是由4个数字组成的矩阵dxx-dxy-dyx-dyy
N-d类似:斜率是N个数的方向向量,
Hessian矩阵在每一点上是N^2个数的矩阵,Laplacians矩阵是1个数的矩阵
(你可能会在网上找到更好的答案
)
为三维函数f工作。我想知道;我只对坡度的大小感兴趣,对方向不感兴趣。如果我计算绝对一阶导数列表项之和的梯度是否足够<代码>二阶导数=np.梯度(求和([df*df表示一阶导数中的d])(为了论证,求和保持形状)好的,我想我现在明白你想要什么了。你只想得到最平坦的区域,或者N维中“最平坦”的意思。我尽量不使用二阶导数,而是计算所有点的绝对梯度(求
np.gradient
结果第一维的平方和,如您在评论中所说),然后从中找到阈值区域,并在阈值区域内找到最小值(如果你的函数足够复杂,那么找到全局极小值可能非常困难)。如果我发现了什么,我会尝试一下并发布另一个答案。@Carsten所有梯度的总和不会产生最平坦的区域;在这个测试案例图片中,它会产生2d高斯的中心。这绝对不是最平坦的区域。因此我认为需要用propper二阶导数而不是第一阶导数来完成。我是cu最近在2D测试用例上对两种建议的解决方案进行了实验(我喜欢看东西)。当说坡度时,我指的是所有方向上最小的;基本上是我能找到的局部最平坦的区域。到目前为止看起来很有希望,但仍有一些测试要做(:我没有空间发布2D测试用例而不污染问题;拉普拉斯和黑森之间的结果差异似乎是它们产生了不同的点。我评估了黑森的拉普拉斯最小值或沿x.dim,x.ndim
的平方和。据我所知,后者采用混合导数我添加了laplace和hessian的2d测试用例的图片。虽然我认为这两种算法都做得很好,但我认为我更喜欢hessian算法,并将其扩展到可变步长;正如讨论的那样,它的工作更正确。编辑:我刚刚看到你对答案的编辑;因此,你可以吗请检查我的图片/代码,并告诉我是否真的做对了(:对于已经实现的Hessian矩阵计算算法,请查看Numdifftools
项目:我认为Hessian是梯度的雅可比矩阵,而不是梯度的梯度。请参见wiki@Srikiran,这在某种程度上是语义问题。雅可比矩阵实际上只是为向量值函数定义的梯度s
f(xy + h) ~ f(xy)
+ slope . h -- dot product, linear in both slope and h
+ h' H h / 2 -- quadratic in h
hessians = np.asarray(np.gradient(np.gradient(f(X, Y))))
hessians[1:]