Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 一维数组的numpy二阶导数_Python_Numpy - Fatal编程技术网

Python 一维数组的numpy二阶导数

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

我有一组模拟数据,我想找到n维中的最低斜率。数据的间距在每个维度上都是恒定的,但并不完全相同(为了简单起见,我可以改变这种间距)

我可以忍受一些数值上的不准确,尤其是边缘。我非常不希望生成样条曲线并使用该导数;仅仅依靠原始值就足够了

使用
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:]