有一个矩阵M,可以分解为3个矩阵U、S、V,使得U x S x V等于M。U与V都是正交矩阵(乘以自身的转置矩阵结果为单位矩阵)。那么S矩阵主对角线上的元素称为矩阵M的奇异值,其它元素均为0。
""" 奇异值分解 """ import numpy as np M = np.mat('4 11 14; 8 7 -2') print(M) """ [[ 4 11 14] [ 8 7 -2]] """ U, sv, V = np.linalg.svd(M, full_matrices=False) print(U,U.shape) """ [[-0.9486833 -0.31622777] [-0.31622777 0.9486833 ]] (2, 2) """ print(sv,sv.shape) #[18.97366596 9.48683298] (2,) print(V,V.shape) """ [[-0.33333333 -0.66666667 -0.66666667] [ 0.66666667 0.33333333 -0.66666667]] (2, 3) """ print(U * U.T) """ [[ 1.00000000e+00 -7.27396709e-17] [-7.27396709e-17 1.00000000e+00]] """ print(V * V.T) """ [[1.00000000e+00 3.08395285e-16] [3.08395285e-16 1.00000000e+00]] """ S = np.diag(sv) print(S) """ [[18.97366596 0. ] [ 0. 9.48683298]] """ #生成原矩阵 print(U * S * V) """ [[ 4. 11. 14.] [ 8. 7. -2.]] """
案例:读取图片的亮度矩阵,提取奇异值与两个正交矩阵,保留部分奇异值,重新生成新的亮度矩阵,绘制图片。
import numpy as np import scipy.misc as sm import matplotlib.pyplot as mp # 读取图片数据,True提取项目矩阵 img = sm.imread('lily.jpg', True) print(img, img.shape) """ [[36.742 35.97 34.97 ... 54.102 54.33 51.042] [37.742 37.742 37.97 ... 54.102 53.33 51.042] [40.34 41.112 40.34 ... 51.732 51.846 50.857] ... [ 5.228 6.228 5.929 ... 71.666 68.954 68.242] [ 6.228 6.228 4.929 ... 73.182 72.182 71.242] [ 6.228 6.228 4.929 ... 69.709 71.709 74.242]] (512, 512) """ # 提取特征值 eigvals, eigvecs = np.linalg.eig(np.mat(img)) #逆向推到原矩阵 eigvals[50:] = 0 #保留50个特征值 img2 = eigvecs*np.diag(eigvals)*eigvecs.I # 绘制图片 mp.figure('Lily', facecolor='lightgray') mp.subplot(221) mp.imshow(img,cmap='gray') mp.xticks([]) mp.yticks([]) mp.subplot(222) mp.imshow(img2.real,cmap='gray') mp.xticks([]) mp.yticks([]) #奇异值分解 U,sv,V = np.linalg.svd(np.mat(img)) sv[50:] = 0 #保留50个奇异值 print(type(U),type(V)) img3 = U*np.diag(sv)*V mp.subplot(224) mp.imshow(img3.real,cmap='gray') mp.xticks([]) mp.yticks([]) mp.tight_layout() mp.show()