两种方法计算矩阵奇异值结果不一致,求技术协助
两种奇异值计算方法结果不一致的原因与修正方案
你遇到的问题核心有两个:
np.linalg.svd返回的奇异值是降序排列的,而np.linalg.eigvals返回的特征值是无序的- 由于数值计算误差,
R.T @ R的特征值可能带有极小的虚部,直接开平方会得到复数
修正步骤:
- 对
R.T @ R的特征值取实部(半正定矩阵的特征值理论上是实数) - 过滤掉极小的非正值(数值误差导致的负数或零)
- 对特征值的平方根进行降序排序,和SVD的结果对齐
修正后的代码:
import matplotlib.pyplot as plt import matplotlib.image as mpimg import numpy as np A = mpimg.imread('sunflower.jpeg') R = A[:,:,0] # 方法1:SVD计算奇异值 U, S_svd, V = np.linalg.svd(R) # 方法2:特征值法修正版 rW = np.linalg.eigvals(np.dot(R.T, R)) # 处理数值误差:取实部,过滤极小负值,开平方后降序排序 singvals_eig = np.sqrt(np.maximum(np.real(rW), 0)) singvals_eig = np.sort(singvals_eig)[::-1] # 截断到和SVD结果一致的长度(取矩阵行列数的较小值) singvals_eig = singvals_eig[:len(S_svd)] # 验证结果一致性(允许浮点计算的微小误差) print(np.allclose(S_svd, singvals_eig)) # 正常会输出True
补充说明:
- 半正定矩阵的特征值理论上非负,但浮点计算中可能出现极小的负数,用
np.maximum(..., 0)可以避免开平方时出现NaN - SVD返回的奇异值数量是矩阵行数和列数的较小值,而
R.T @ R的特征值数量等于列数,所以要截断到和SVD一致的长度 - 用
np.allclose对比结果,允许浮点计算的微小误差,而非直接判断数值完全相等
内容的提问来源于stack exchange,提问作者TheIndex
相关产品推荐
相关产品推荐

