奇异值分解(singular value decomposition,SVD)
文章目录
- 一、奇异值分解的定义
- 二、奇异值分解的计算步骤(间接法求 UUU)
- 三、奇异值分解的几何意义
- 四、奇异值分解的典型应用
- 五、间接法求 UUU 的核心优势
- 六、SVD 实战
- 基本运算及数据压缩
- 图片压缩
一、奇异值分解的定义
奇异值分解是将任意矩阵分解为三个特殊矩阵乘积的过程。对于 m×nm \times nm×n 矩阵 AAA,其奇异值分解表达式为:
A=UΣVTA = U\Sigma V^T A=UΣVT其中各矩阵的核心性质:
-
UUU(左奇异矩阵):m×mm \times mm×m 正交矩阵,满足 UTU=IU^T U = IUTU=I,列向量为左奇异向量;
-
Σ\SigmaΣ(奇异值矩阵):m×nm \times nm×n 对角矩阵,对角线元素为非负奇异值(按降序排列),非对角线元素为 0;
-
VVV(右奇异矩阵):n×nn \times nn×n 正交矩阵,满足 VTV=IV^T V = IVTV=I,列向量为右奇异向量。
二、奇异值分解的计算步骤(间接法求 UUU)
以下通过示例详细说明仅通过 ATAA^T AATA 计算 SVD 的完整流程。
示例矩阵
选择 3×23 \times 23×2 矩阵 AAA(m=3,n=2m=3, n=2m=3,n=2,含零行,贴近实际数据场景):
A=(200100)A = \begin{pmatrix} 2 & 0 \\ 0 & 1 \\ 0 & 0 \end{pmatrix}A=200010
步骤一:计算 ATAA^T AATA
AT=(200010)A^T = \begin{pmatrix} 2 & 0 & 0 \\ 0 & 1 & 0 \end{pmatrix} AT=(200100)M=ATA=(200010)(200100)=(4001)M = A^T A = \begin{pmatrix} 2 & 0 & 0 \\ 0 & 1 & 0 \end{pmatrix} \begin{pmatrix} 2 & 0 \\ 0 & 1 \\ 0 & 0 \end{pmatrix} = \begin{pmatrix} 4 & 0 \\ 0 & 1 \end{pmatrix}M=ATA=(200100)200010=(4001)
步骤二:求解 ATAA^T AATA 的特征值;
特征值是满足特征方程 det(M−λI)=0\det(M - \lambda I) = 0det(M−λI)=0 的 λ\lambdaλ 值(III 为单位矩阵,det(.)\det(.)det(.)表示求行列式),具体计算过程为:
det(4−λ001−λ)=(4−λ)(1−λ)=0\det\begin{pmatrix} 4-\lambda & 0 \\ 0 & 1-\lambda \end{pmatrix} = (4-\lambda)(1-\lambda) = 0 det(4−λ001−λ)=(4−λ)(1−λ)=0解得特征值:λ1=4\lambda_1 = 4λ1=4,λ2=1\lambda_2 = 1λ2=1(按降序排列)。
步骤三:构造右奇异矩阵 VVV
该步骤利用 MMM 的特征向量来构造右奇异矩阵 VVV
特征向量需满足 (M−λI)v=0(M - \lambda I)\mathbf{v} = \mathbf{0}(M−λI)v=0,且需单位化:
-
对 λ1=4\lambda_1 = 4λ1=4:
(000−3)(v11v12)=0⟹v12=0\begin{pmatrix} 0 & 0 \\ 0 & -3 \end{pmatrix} \begin{pmatrix} v_{11} \\ v_{12} \end{pmatrix} = \mathbf{0} \implies v_{12} = 0 (000−3)(v11v12)=0⟹v12=0取单位特征向量 v1=(10)\mathbf{v}_1 = \begin{pmatrix} 1 \\ 0 \end{pmatrix}v1=(10) -
对 λ2=1\lambda_2 = 1λ2=1:
(3000)(v21v22)=0⟹v21=0\begin{pmatrix} 3 & 0 \\ 0 & 0 \end{pmatrix} \begin{pmatrix} v_{21} \\ v_{22} \end{pmatrix} = \mathbf{0} \implies v_{21} = 0 (3000)(v21v22)=0⟹v21=0取单位特征向量 v2=(01)\mathbf{v}_2 = \begin{pmatrix} 0 \\ 1 \end{pmatrix}v2=(01)
因此,右奇异矩阵为:
V=(v1v2)=(1001)V = \begin{pmatrix} \mathbf{v}_1 & \mathbf{v}_2 \end{pmatrix} = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix}V=(v1v2)=(1001)
步骤四:构造奇异值矩阵 Σ\SigmaΣ
奇异值为特征值的平方根:σi=λi\sigma_i = \sqrt{\lambda_i}σi=λi,故 σ1=2\sigma_1 = 2σ1=2,σ2=1\sigma_2 = 1σ2=1。
Σ\SigmaΣ 为 m×nm \times nm×n 对角矩阵(非对角元素补 0):
Σ=(200100)\Sigma = \begin{pmatrix} 2 & 0 \\ 0 & 1 \\ 0 & 0 \end{pmatrix}Σ=200010
步骤五:间接法构造左奇异矩阵 UUU
核心公式:
ui=1σiAvi\mathbf{u}_i = \frac{1}{\sigma_i} A \mathbf{v}_iui=σi1Avi
1. 计算主左奇异向量(U1U_1U1)
u1=1σ1Av1=12(200100)(10)=(100)\mathbf{u}_1 = \frac{1}{\sigma_1} A\mathbf{v}_1 = \frac{1}{2} \begin{pmatrix} 2 & 0 \\ 0 & 1 \\ 0 & 0 \end{pmatrix} \begin{pmatrix} 1 \\ 0 \end{pmatrix} = \begin{pmatrix} 1 \\ 0 \\ 0 \end{pmatrix}u1=σ11Av1=21200010(10)=100
u2=1σ2Av2=(200100)(01)=(010)\mathbf{u}_2 = \frac{1}{\sigma_2} A\mathbf{v}_2 =\begin{pmatrix} 2 & 0 \\ 0 & 1 \\ 0 & 0 \end{pmatrix} \begin{pmatrix} 0 \\ 1 \end{pmatrix}= \begin{pmatrix} 0 \\ 1 \\ 0 \end{pmatrix}u2=σ21Av2=200010(01)=010
因此主左奇异矩阵:U1=(u1u2)=(100100)U_1 = \begin{pmatrix} \mathbf{u}_1 & \mathbf{u}_2 \end{pmatrix} = \begin{pmatrix} 1 & 0 \\ 0 & 1 \\ 0 & 0 \end{pmatrix}U1=(u1u2)=100010
2. 补充正交补向量(关键:区分 UUU 和 VVV 的补充条件)
UUU 是 m×mm \times mm×m 正交矩阵,需 mmm 个正交向量。当 m>rank(A)=rm > \text{rank}(A) = rm>rank(A)=r 时,需补充 m−rm - rm−r 个向量(与 U1U_1U1 列向量正交且单位化)。
本例中,需为 UUU 补充 m−r=3−2=1m - r=3-2=1m−r=3−2=1 个正交补向量:
设 u3=(x1x2x3)\mathbf{u}_3 = \begin{pmatrix} x_1 \\ x_2 \\ x_3 \end{pmatrix}u3=x1x2x3,需满足 u1Tu3=0\mathbf{u}_1^T \mathbf{u}_3 = 0u1Tu3=0 且 u2Tu3=0\mathbf{u}_2^T \mathbf{u}_3 = 0u2Tu3=0,则有:
x1=x2=0x_1 = x_2 = 0 x1=x2=0则取单位向量 u3=(001)\mathbf{u}_3 = \begin{pmatrix} 0 \\ 0 \\ 1 \end{pmatrix}u3=001
因此正交补矩阵:U2=(u3)=(001)U_2 = \begin{pmatrix} \mathbf{u}_3 \end{pmatrix} = \begin{pmatrix} 0 \\ 0 \\ 1 \end{pmatrix}U2=(u3)=001
3. 完整左奇异矩阵 UUU
U=(U1U2)=(100010001)U = \begin{pmatrix} U_1 & U_2 \end{pmatrix} = \begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{pmatrix}U=(U1U2)=100010001
验证分解结果
UΣVT=(100010001)(200100)(1001)=(200100)=AU\Sigma V^T = \begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} 2 & 0 \\ 0 & 1 \\ 0 & 0 \end{pmatrix} \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix} = \begin{pmatrix} 2 & 0 \\ 0 & 1 \\ 0 & 0 \end{pmatrix} = AUΣVT=100010001200010(1001)=200010=A
分解成立。
三、奇异值分解的几何意义
矩阵 AAA 对向量的变换可拆解为三步:
-
旋转 / 反射:VTV^TVT 将向量映射到标准正交基;
-
缩放:Σ\SigmaΣ 沿坐标轴按奇异值比例缩放(奇异值为缩放因子);
-
旋转 / 反射:UUU 将向量映射回原空间。
奇异值大小反映对应方向的 “重要性”,越大则该方向在变换中起主导作用。
四、奇异值分解的典型应用
-
数据降维
保留前 kkk 个最大奇异值,用 UkΣkVkTU_k \Sigma_k V_k^TUkΣkVkT 近似原矩阵,实现高维数据压缩。例如 PCA 本质是通过 SVD 提取数据主成分。
-
图像压缩
图像矩阵经 SVD 分解后,通过 A≈∑i=1kσiuiviTA \approx \sum_{i=1}^k \sigma_i \mathbf{u}_i \mathbf{v}_i^TA≈∑i=1kσiuiviT 还原,仅需存储 kkk 个奇异值及向量(k≪min(m,n)k \ll \min(m,n)k≪min(m,n)),大幅减少存储空间。
-
推荐系统
对用户 - 物品评分矩阵做 SVD,提取潜在特征(如用户偏好、物品属性),预测未评分物品分值,提升推荐精度。
五、间接法求 UUU 的核心优势
-
计算效率
当 m≫nm \gg nm≫n 时,ATAA^T AATA 为 n×nn \times nn×n 矩阵(维度远小于 AATAA^TAAT 的 m×mm \times mm×m),特征值计算更高效。
-
正交性保障
若 VVV 列向量正交,则 UUU 列向量自动正交(由线性变换性质保证),无需额外正交化处理。
通过间接法计算 SVD,既能简化复杂矩阵的分解过程,又能深刻理解左 / 右奇异向量与矩阵变换的内在联系,为实际工程应用提供坚实理论支撑。
六、SVD 实战
基本运算及数据压缩
在 SVD(奇异值分解)的矩阵压缩 / 近似场景中,k 表示保留的奇异值数量(取前 k 个最大的奇异值),其核心思想是:大的奇异值包含矩阵的主要信息,保留前 k 个奇异值即可用低秩矩阵近似原始矩阵。
SVD 的展开形式公式如下:
A=UΣVT=∑i=1rσi⋅ui⋅viTA = U \Sigma V^T = \sum_{i=1}^r \sigma_i \cdot u_i \cdot v_i^T A=UΣVT=i=1∑rσi⋅ui⋅viT当使用前 k 个奇异值进行近似时:
Ak=∑i=1kσi⋅ui⋅viTA_k = \sum_{i=1}^k \sigma_i \cdot u_i \cdot v_i^T Ak=i=1∑kσi⋅ui⋅viT
import numpy as np
from numpy import linalg as la
def compute_SVD(A):"""function: compute singular value decompositioninput: the matrix (m, n) you want to compute the SVDoutput:U (m, m),s (1, n), 注意这里为了节省空间只输出一维,后续需要转化VT (n, n)"""A = np.array(A) # 将输入的矩阵 A(以 Python 列表形式表示)转换为 NumPy 数组U, s, VT = la.svd(A)return U, s, VTif __name__ == '__main__':A = [[1, 1, 3, 6, 1], [5, 1, 8, 4, 2], [7, 9, 2, 1, 2]]print("原始矩阵:\n", A)# SVD奇异值分解U, s, VT = compute_SVD(A)Sigma = np.zeros((U.shape[0], VT.shape[0]))np.fill_diagonal(Sigma, s) # 构造对角矩阵 Σprint("左奇异矩阵:\n", U)print("奇异值矩阵\n", Sigma)print("右奇异矩阵的转置\n", VT)# SVD重构验证A_reconstructed = U @ Sigma @ VT # 在 NumPy 中,@ 是矩阵乘法的运算符print("重构后的矩阵:\n", A_reconstructed)print('原矩阵与重构矩阵是否相同?', np.allclose(A, A_reconstructed))# SVD矩阵压缩(降维)for k in range(3, 0, -1): # 3,2,1# 保留U的前k列,VT的前k行,前k个奇异值D = U[:, :k] @ Sigma[:k, :k] @ VT[:k, :]print('k=', k, "压缩后的矩阵:\n", np.round(D)) # round取整数
运行结果:
图片压缩
原理和上面的数据压缩一样。数字图像在计算机中以矩阵形式存储,每个像素对应矩阵中的一个元素。灰度图像的矩阵为二维,彩色图像的矩阵为三维(通常为高度、宽度和颜色通道)。RGBA 图像形状为 (高度, 宽度, 4),第四通道表示透明度(Alpha)。多光谱图像:形状可能为 (高度, 宽度, n),n 为波段数(如卫星图像)。下面用彩色图像来举例,我们可以分别从三种颜色通道中把二维矩阵提取出来。
import numpy as np
from PIL import Imagedef img_compress_compute1(img, percent):"""function: 根据奇异值数值总和的百分比对图片进行压缩:param img: 图片矩阵,这里只保留宽和高两维:param percent: 压缩比例:return: 压缩后图片矩阵"""# SVD计算U, s, VT = np.linalg.svd(img)Sigma = np.zeros(np.shape(img))Sigma[:len(s), :len(s)] = np.diag(s)# 压缩图片count = (int)(sum(s))*percent # 保留奇异值总和k = -1SV_sum = 0while SV_sum <= count:k += 1SV_sum += s[k]img_compressed = U[:, :k] @ Sigma[:k, :k] @ VT[:k, :]# 纠正异常值# img_compressed [img_compressed < 0] = 0# img_compressed [img_compressed > 255] = 255return np.rint(img_compressed).astype('uint8')def img_compress_compute2(img, percent):"""function: 根据奇异值个数的百分比对图片进行压缩:param img: 图片矩阵,这里只保留宽和高两维:param percent: 压缩比例:return: 压缩后图片矩阵"""# SVD计算U, s, VT = np.linalg.svd(img)Sigma = np.zeros(np.shape(img))Sigma[:len(s), :len(s)] = np.diag(s)# 压缩图片k = (int)(len(s))*percentimg_compressed = U[:, :k] @ Sigma[:k, :k] @ VT[:k, :]# 纠正异常值# img_compressed [img_compressed < 0] = 0# img_compressed [img_compressed > 255] = 255return np.rint(img_compressed).astype('uint8')def img_compress(filename, percent):"""function: 压缩图片:param filename: 图片路径:param percent: 压缩比:return: null"""img = Image.open(filename, 'r')a = np.array(img)# 提取图片三通道矩阵R0 = a[:, :, 0]G0 = a[:, :, 1]B0 = a[:, :, 2]# 分别对三种颜色通道进行压缩R = img_compress_compute1(R0, percent)G = img_compress_compute1(G0, percent)B = img_compress_compute1(B0, percent)img_reconstructed = np.stack((R, G, B), axis=2)# 保存图片newfile = filename + str(percent*100) + '.png'Image.fromarray(img_reconstructed).save(newfile)# img.show()for i in range(10):print(i)img_compress('img/girl.jpg', i / 10)
对比结果(这里我们使用的图片压缩比为奇异值数值总和的百分比):
我们可以看到压缩比为60%以上在很大程度上已经还原了图片,这也说明,我们可以用更少的数据来存储图片。
参考
【1】【推荐算法】MF矩阵分解 – SVD、LFM、RSVD、SVD++.老弓的学习日记.哔哩哔哩
【2】【彻底搞懂】矩阵奇异值分解(SVD).牙非涯.知乎