特征分解和奇异值分解(SVD)

特征分解

若方阵 AR n×n   ,存在 vR n   λR  ,使得: Av=λv  ,则 v  称为 A  的(右)特征向量, λ  称为 A  的特征值。

将所有的特征向量按列排成一个矩阵 V  ,则有: A=VΛV 1   ,其中 Λ  是所有的特征值构成的对角矩阵。该式称为 A  的特征分解。

特别地,若 A  是对称矩阵,则有 A=QΛQ 1 =QΛQ T   ,其中 Q  是正交矩阵。

奇异值分解(SVD)

AR m×n   是非方阵,则不能对其进行特征分解,但可以进行奇异值分解: A=UΣV T   ,其中 UR m×m   为正交阵, ΣR m×n   为对角阵(不一定是方阵), VR n×n   为正交阵。

奇异值分解可以用特征分解来解释,设 A=UΣV T   ,则有:
- AA T =UΣV T VΣU T =UΣ 2 U T  
。可见, A  的奇异值分解中的 U  就是对称阵 AA T   的特征向量, Σ  则是 AA T   的特征值的平方根。
- A T A=VΣU T UΣV T =VΣ 2 V T  
。可见, A  的奇异值分解中的 V  就是对称阵 A T A  的特征向量, Σ  则是 A T A  的特征值的平方根。

SVD分解能用于数据压缩:
- 通过 A m×n =U m×m Σ m×n V T n×n   ,求解 U  Σ  V 
- 将 Σ  中的奇异值从大到小排序,对应 U  V  的列向量也重新排序
- 取前 k  个奇异值对应的 U ^  m×k   Σ ^  k×k   V ^  n×k   ,计算 A  的近似矩阵 A ^  m×n =U ^ Σ ^ V ^  T  

此时所需的存储量为 mk+k+nk=k(m+n+1)  ,若 k<mnm+n+1   ,就能起到压缩的作用。实际上,对于图像这样的数据,当 k<mnm+n+1   时,也能保留视觉上的大部分信息。

import math
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

# 读取图片
X = np.array(Image.open(".\_data\son.jpg").convert('L'), 'f') # M*N
M = X.shape[0]
N = X.shape[1]

U, s, V = np.linalg.svd(X) # 奇异值分解(均已按 s 中的奇异值降序排列)
S = np.zeros((M, N))
S[0:M, 0:M] = np.diag(s)

plt.subplots(figsize=(20,10))
r, c, i = (5, 6, 1)

for k in range(M, 0, -math.ceil(M/(r*c))):
    Uk = U[:, 0:k] # M*k
    Sk = S[0:k, 0:k] # k*k
    Vk = V[0:k, :] # k*N
    X_ = Uk.dot(Sk).dot(Vk) # M*N
    ratio = 1.0*k*(M+N+1)/(M*N)
    plt.subplot(r, c, i, title='↓k=%d, ratio=%.1f' % (k, ratio)).axis('off')
    plt.imshow(Image.fromarray(X_))
    i+=1

plt.axis('off')
plt.show()

特征分解和奇异值分解(SVD)_第1张图片

你可能感兴趣的:(特征分解和奇异值分解(SVD))