SVD分解圖片重構計算


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) 進行重構

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章