SVD分解图片重构计算

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ouening/article/details/81814020

2018-08-19更新
(1)添加scikit-learn中使用PCA实现的方法,主要使用到了

inverse_transform(X)
这里写图片描述
可以实现重构

(2)修改了参与重构的奇异值数量比例变化


查看scipy cheet sheet的时候看到了svd矩阵分解,写了个简单的分解图像并且重构应用。SVD的帮助文档在numpy里面比较齐全,可以同时参考numpy,scipy和scikit-learn的文档
(1)https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.linalg.svd.html
(2)https://docs.scipy.org/doc/scipy-0.19.0/reference/generated/scipy.linalg.svd.html
(3)http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html#sklearn.decomposition.PCA.inverse_transform
下面直接上代码,已有详细注释

'''
使用SVD分解图片
Singular Value Decomposition.

When a is a 2D array, it is factorized as u @ np.diag(s) @ vh = (u * s) @ vh, where u and vh are 2D unitary arrays and s is a 1D array of a‘s singular values. When a is higher-dimensional, SVD is applied in stacked mode as explained below.
'''
## 1 导入相关库
import matplotlib.pyplot as plt
import numpy as np
from scipy.misc import face # 该库里面有示例图片face
from scipy.linalg import svd,eig,diagsvd,lu
import skimage

## 2 载入图片,灰度化
imgrgb = face()
img = skimage.color.rgb2gray(imgrgb)
print(img.shape) # (768, 1024)
## 3 svd分解
u, s, vh = svd(img)
print(u.shape,s.shape,vh.shape) #(768, 768) (768,) (1024, 1024)

## 4 使用奇异值重构
'''
根据结果可知奇异值有768个,从大到小排列,下面分别选取10,25,50,80,100个奇异值进行重构
'''

num_of_singular = [5,10,20,40,80]

plt.figure()
plt.title('A=U*S*Vh')
for index,i in enumerate(num_of_singular) :
    reconstruct = np.dot(u[:,:i]*s[:i],vh[:i,:]) # 注意这个重构的矩阵运算
    plt.subplot(1,len(num_of_singular),index+1)
    plt.xticks([])
    plt.yticks([])
    plt.title("Num of Singular :{}".format(i))
    plt.imshow(reconstruct,cmap=plt.cm.gray)



## 5 使用scikit-learn中的PCA方法实现
from sklearn.decomposition import PCA
plt.figure()
plt.title('scikit-learn PCA')
for index,i in enumerate(num_of_singular) :
    '''
    使用PCA
    '''
    pca = PCA(n_components = i)
    singular = pca.fit_transform(img) # shape (n_samples, n_components)
    reconstruct = pca.inverse_transform(singular) # shape (n_samples, n_features) 
    plt.subplot(1,len(num_of_singular),index+1)
    plt.xticks([])
    plt.yticks([])
    plt.title("Num of Singular :{}".format(i))
    plt.imshow(reconstruct,cmap=plt.cm.gray)

plt.show()

结果如下:
这里写图片描述
注意到奇异值数量为20的时候重构的图像已经很好了,此时占所有奇异值数量比例为25/768=3.25%,也就是说用这么少的数据就可以重构效果还不错的图像,实现了数据的压缩。

注意
(1)重构的时候u矩阵和vh矩阵大小要作相应改变,不然矩阵维数不对是无法进行矩阵乘法运算重构的,重构关键代码是

reconstruct = np.dot(u[:,:i]*s[:i],vh[:i,:])

(2)使用PCA方法使用inverse_transform(X) 进行重构

猜你喜欢

转载自blog.csdn.net/ouening/article/details/81814020