使用 numpy.linalg.inverse 和倒数有什么区别?

What's the difference between the use of numpy.linalg.inverse and reciprocal?

我目前正在研究光谱梯度法。现在我开发了两种相似的算法,但显然,当我认为它们产生相同的结果时,它们实际上 return 经过一些迭代后的不同值。

这是变量

v (vector at kth iteration)
v_1 (vector at k+1th iteration)
g (gradient at kth iteration)
g_1 (gradient at k+1th iteration)

第一种算法如下:

def spectral_grad1(
    v: np.ndarray, v_1: np.ndarray,
    g: np.ndarray, g_1: np.ndarray
    ) -> np.ndarray:

    s = v_1 - v
    y = g_1 - g

    sT_y = s.T@y
    sT_s = s.T@s

    if s.T_s > s.T_y:
        s1 = s**4
        s2 = s**2
        w_k = (sT_s - sT_y) / s1.sum()
        B_k  = np.array([1. / (1.+ w_k*i) for i in s2])
        return np.diag(B_k)

    return np.identity(len(s)) #rescaling

direction = np.negative(np.linalg.inv(B) @ g)

另一方面,这是第二种算法:

def spectral_grad2(
    v: np.ndarray, v_1: np.ndarray,
    g: np.ndarray, g_1: np.ndarray
    ) -> np.ndarray:
    
    s = v_1 - v
    y = g_1 - g
    
    sT_y = s.T@y
    sT_s = s.T@s

    if sT_s <= sT_y:
        return np.identity(len(v)) # Rescaling

    s1 = s**4
    s2 = s**2
    w_k = (sT_s - sT_y) / s1.sum()
    B_k = 1. + w_k*s2
    return np.diag(B_k) # Diagonal matrix of B

direction = -(B @ g)

如果你看一下这两个算法,唯一的区别是B_kdirection的计算。

很抱歉,因为这只是梯度下降算法的一部分,所以我无法提供太多数据来重现这一点。我更好奇的是,是什么让两种算法中的 B_kdirection 产生不同的结果?

编辑

我想找到 B_k 的倒数。因此,任何关于使用倒数或 np.linalg.inv 的见解都将不胜感激

在其中一个中,您有效地使用了:

diag([1. / (1.+ w_k*i) ...])

另一个

linalg.inv(diag(1. + w_k*s2))

请注意,对角矩阵 的理论逆是 对角矩阵的倒数。但是 linalg.inv 不知道它的输入是对角线的,因此产生的数值逆可能有一些非常小的非零值 off-diagonal.