我正在尝试使用np.linalg.eig
方法来实现SVD进行图像压缩分配。我们不允许直接使用np.linalg.svd
方法。
这是我的svd方法:
def svd(A):
evals, U = LA.eig(A @ A.T)
evals2, V = LA.eig(A.T @ A)
idx = evals.argsort()[::-1]
evals = evals[idx]
U = U[:, idx]
idx = evals2.argsort()[::-1]
V = V[ :, idx]
sigma = np.array(list(map(math.sqrt, evals)))
return U, sigma, V.T
但是当我尝试使用上述svd返回的U和V重建图像时,错误率是如此之高,甚至在使用所有奇异矢量后,图像也完全模糊。而当我对np.linalg.svd
返回的U&V矩阵尝试相同的重建过程时,我能够清晰地重建图像。
请让我知道我的svd方法是否有问题。
SVD和特征向量都不完全唯一。在SVD中,您可以对U中的任何向量进行符号翻转,只要对V中的相应向量进行翻转即可。获得的特征向量不以这种方式耦合,因此,符号失配的可能性很大。您可以通过使用UT @ A @ VT是sigma的事实来进行检查和校正,因此请检查UT @ A @ VT的对角元素的符号,并对每个负数翻转U或V中的对应矢量(但两者都不是。
其他建议:
由于只需要对角线元素,因此计算完整乘积U.T @ A @ V.T是浪费的;仅计算对角线元素的最简单方法是np.einsum('ij,ik,jk->j',U,A,V)
。
使用eigh
而不是eig
,因为您知道[email protected]和A.T@A是对称的。
您可以保存一个特征分解,因为sigma @ V = U.T@A并且sigma对角线很容易反转。这还具有不会发生上述标志问题的优点。