Python 利用eig实现SVD
我正在尝试使用Python 利用eig实现SVD,python,numpy,svd,Python,Numpy,Svd,我正在尝试使用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()[:
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)中,只要对V中相应的向量进行同样的操作,就可以对U中的任何向量进行符号翻转。得到的特征向量不是以这种方式耦合的,因此符号不匹配的可能性很大。你可以通过使用以下事实来检查和纠正。T@A@V.T是sigma,所以检查U的对角线元素的符号。T@A@V.T,对于每个负向量,翻转U或V中的相应向量(但不是同时翻转) 其他建议: 由于您只需要对角线元素,因此计算完整乘积U是浪费的。T@A@V.T;只计算对角线元素的最简单方法是
np.einsum('ij,ik,jk->j',U,A,V)
使用eig
而不是eig
,因为您知道A@A.T和A。T@A它们是对称的
您可以保存一个特征分解,因为sigma@V=U。T@Asigma是对角的,很容易倒置。这还有一个优点,就是上面的符号问题不会发生。对于一般矩阵,奇异值分解和特征值分解不以这种方式相关。只有正规矩阵和半正定矩阵才有这种关系,显然你的图像不是这样的矩阵。有关更多信息,请参阅。根据SVD的定义实现。它适用于任何m*n实矩阵。他们提到的是EVD的一个特例。