Math——奇异值分解-SVD

本文从不同角度给出奇异值分解的物理意义


公式说明

$$A=U\Sigma V^{T}$$

  • \(U,V\)都是正交矩阵,\(\Sigma\)是对角矩阵,对角上的元素是矩阵\(A\)的奇异值
  • 若保留对角元素最大的K个值
    • \(K=r=Rank(A)\)时为紧奇异值分解,对应的是无损压缩,此时由于奇异值保留数量与原始矩阵相同,能做到对原始矩阵A的完全还原
    • \(K< r=Rank(A)\)时为截断奇异值分解,对应的是有损压缩,此时由于奇异值保留数量比原始矩阵的小,做不到对原始矩阵A的完全还原,但是如果K足够大就能做到对矩阵A的较完美近似

图像处理方面

  • 直观上可以理解为奇异值分解是将矩阵分解为若干个秩一矩阵之和,用公式表示就是:
    $$A=\sigma_{1}u_{1}v_{1}^{T}+\sigma_{2}u_{2}v_{2}^{T}+…+\sigma_{r}u_{r}v_{r}^{T}$$
    • 式子中每一项的系数\(\sigma\)就是奇异值
    • \(u,v\)都是列向量,每一个\(uv^{T}\)都是秩为1的矩阵
    • 奇异值按照从小到大排列
  • 从公式中按照从大到小排序后,保留前面系数最大的项目后效果
    • 对于一张450x333的图片,只需要保留前面的50项即可得到相当清晰的图像
    • 从保留项1到50,图片越来越清晰
  • 结论:
    • 奇异值越大的项,越能体现出来图片的效果,奇异值隐含着某种对于A矩阵来说很重要的信息
    • 加权的秩一矩阵能体现整个大矩阵的值,奇异值就是对应秩一矩阵对于A矩阵的权重

线性变换方面

几何含义

  • 对于任何的一个矩阵,我们要找到一组两两正交单位向量序列,使得矩阵作用在此向量序列上后得到新的向量序列保持两两正交.奇异值的几何含义为:这组变换后的新的向量序列的长度

更直观的几何含义

  • 公式:
    $$E_{m}={y\in C^{m}: y=Ax, x\in C^{n},\left | x\right |_{2}=1}$$
  • 二维矩阵A:
    • 矩阵A将二维平面中的单位圆变换为椭圆,而两个奇异值正好是椭圆的半轴长度.
  • m维矩阵
    • 矩阵A将高维平面中的单位球变换为超椭球,矩阵的奇异值恰好就是超椭球的每条半轴长度.

奇异值分解的降维理解

代码编写

  • 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    ##encoding=utf-8
    import numpy as np

    A = np.array([[4, 5, 6], [4, 5, 6], [8, 10, 12], [4, 5, 6]])

    print("原始矩阵:")
    print(A)

    U, Sigma, Vt = np.linalg.svd(A)
    U = np.array(U)
    Sigma = np.array(Sigma)
    Vt = np.array(Vt)

    print("分解后的原始U,S,V:")
    print(U)
    Sigma_ = np.zeros((4, 3), dtype=np.float64)
    Sigma_[:3][:3] = np.diag(Sigma)
    print Sigma_
    print(Vt)

    # 不做任何处理,直接恢复原始矩阵
    A_ = np.dot(np.dot(U, Sigma_), Vt)
    print(A_)

    # 原始矩阵的秩为1,所以可以拆解到只剩下一个奇异值,压缩到一维,也能完整恢复原始矩阵,实现将4x3的矩阵变成两个向量+一个数字,当矩阵维度变大时,这里的压缩会更加明显
    U = U[:, :1]
    Sigma_ = Sigma_[:1, :1]
    Vt = Vt[:1, :]

    print("降维后的U,S,V:")
    print(U)
    print(Sigma_)
    print(Vt)
    A_ = np.dot(np.dot(U, Sigma_), Vt)
    print("降维后的恢复矩阵,与原矩阵相同:")
    print(A_)
  • 结果

    原始矩阵:
    [[ 4 5 6]
    [ 4 5 6]
    [ 8 10 12]
    [ 4 5 6]]
    分解后的原始U,S,V:
    [[-3.77964473e-01 -9.25820100e-01 1.52792960e-16 0.00000000e+00]
    [-3.77964473e-01 1.54303350e-01 9.12870929e-01 0.00000000e+00]
    [-7.55928946e-01 3.08606700e-01 -3.65148372e-01 -4.47213595e-01]
    [-3.77964473e-01 1.54303350e-01 -1.82574186e-01 8.94427191e-01]]
    [[2.32163735e+01 0.00000000e+00 0.00000000e+00]
    [0.00000000e+00 1.22295087e-15 0.00000000e+00]
    [0.00000000e+00 0.00000000e+00 5.18334466e-32]
    [0.00000000e+00 0.00000000e+00 0.00000000e+00]]
    [[-0.45584231 -0.56980288 -0.68376346]
    [ 0.02454097 0.75988299 -0.64959647]
    [-0.88972217 0.31289378 0.3324033 ]]
    [[ 4. 5. 6.]
    [ 4. 5. 6.]
    [ 8. 10. 12.]
    [ 4. 5. 6.]]
    降维后的U,S,V:
    [[-0.37796447]
    [-0.37796447]
    [-0.75592895]
    [-0.37796447]]
    [[23.21637353]]
    [[-0.45584231 -0.56980288 -0.68376346]]
    降维后的恢复矩阵,与原矩阵相同:
    [[ 4. 5. 6.]
    [ 4. 5. 6.]
    [ 8. 10. 12.]
    [ 4. 5. 6.]]