使用 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_k
和direction
的计算。
很抱歉,因为这只是梯度下降算法的一部分,所以我无法提供太多数据来重现这一点。我更好奇的是,是什么让两种算法中的 B_k
和 direction
产生不同的结果?
编辑
我想找到 B_k
的倒数。因此,任何关于使用倒数或 np.linalg.inv
的见解都将不胜感激
在其中一个中,您有效地使用了:
diag([1. / (1.+ w_k*i) ...])
另一个
linalg.inv(diag(1. + w_k*s2))
请注意,对角矩阵 的理论逆是 对角矩阵的倒数。但是 linalg.inv
不知道它的输入是对角线的,因此产生的数值逆可能有一些非常小的非零值 off-diagonal.
我目前正在研究光谱梯度法。现在我开发了两种相似的算法,但显然,当我认为它们产生相同的结果时,它们实际上 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_k
和direction
的计算。
很抱歉,因为这只是梯度下降算法的一部分,所以我无法提供太多数据来重现这一点。我更好奇的是,是什么让两种算法中的 B_k
和 direction
产生不同的结果?
编辑
我想找到 B_k
的倒数。因此,任何关于使用倒数或 np.linalg.inv
的见解都将不胜感激
在其中一个中,您有效地使用了:
diag([1. / (1.+ w_k*i) ...])
另一个
linalg.inv(diag(1. + w_k*s2))
请注意,对角矩阵 的理论逆是 对角矩阵的倒数。但是 linalg.inv
不知道它的输入是对角线的,因此产生的数值逆可能有一些非常小的非零值 off-diagonal.