这是我的代码
import numpy as np
def svd(A):
eigvals_left, eigvecs_left = np.linalg.eig(A @ A.T)
eigvals_right, eigvecs_right = np.linalg.eig(A.T @ A)
sigma = np.sqrt(np.abs(eigvals_right))
num = min(A.shape)
sorted_indices = np.argsort(-sigma)
sigma = sigma[sorted_indices[:num]]
U = eigvecs_left[:, np.argsort(-eigvals_left)[:num]]
V = eigvecs_right[:, np.argsort(-eigvals_right)[:num]]
return U, sigma, V.T
h = np.random.rand(2, 3)
print(h)
j, k, l = svd(h)
x, y, z = np.linalg.svd(h, compute_uv=True, full_matrices=False)
print('---------------')
print(j @ np.diag(k) @ l)
print('---------------')
print(x @ np.diag(y) @ z)
print('---------------')
print(l @ z.T)
我很困惑。大多数情况下,l 和 z 的绝对值相似,但 1 和 z 之间总是存在符号差异。我已经正确排序了 eigvec。 l 和 z 转置相乘得到的矩阵也类似于对角矩阵,但符号有时为正,有时为负。
输出1:
[[0.53221807 0.59786549 0.09906266]
[0.4031512 0.38389025 0.16900433]]
---------------
[[-0.55253742 -0.55534658 -0.19184685]
[-0.37481911 -0.44317609 -0.03963159]]
---------------
[[0.53221807 0.59786549 0.09906266]
[0.4031512 0.38389025 0.16900433]]
---------------
[[ 1.00000000e+00 7.40766293e-17]
[-4.02870278e-17 1.00000000e+00]]
输出2:
[[0.23044744 0.86795113 0.64293873]
[0.80871952 0.17031212 0.33708637]]
---------------
[[0.23044744 0.86795113 0.64293873]
[0.80871952 0.17031212 0.33708637]]
---------------
[[0.23044744 0.86795113 0.64293873]
[0.80871952 0.17031212 0.33708637]]
---------------
[[-1.00000000e+00 -2.56188682e-16]
[-4.53777597e-16 1.00000000e+00]]
特征向量的符号(更一般地说是相位)是任意的,两种不同的算法可能会输出不同的符号。对于 SVD,奇异向量的符号是 SVD 定义中的规范自由度。
如果您有 SVD
M = U @ S @ V
,其中 S
是对角线,U
和 V
是酉,则 U
列和 V
行上的任何符号变化也会给出 SVD。
n = 10
M = np.random.random((n, n))
U, s, V = np.linalg.svd(M)
S = np.diag(s)
print(np.allclose(M, U @ S @ V))
random_signs = 1 - 2 * (np.random.random(n) > 0.5)
D = np.diag(random_signs)
U2 = U @ D
V2 = D @ V
print(np.allclose(M, U2 @ S @ V2))
在奇异值不存在简并性的情况下,这是 SVD 中唯一的自由度。已经提出了一些算法来修复这个仪表。
有关 SVD 仪表的更多详细信息,请参见https://www.sciencedirect.com/science/article/pii/037704278890386X?via%3Dihub