【MQ筆記】SVD分解練習(Python)(矩陣分解,圖像處理,求解超定方程)

目錄

 

直接對矩陣進行奇異值分解

利用SVD分解壓縮圖像

利用SVD分解求超定方程的解


直接對矩陣進行奇異值分解

已知矩陣\boldsymbol{A}=\begin{bmatrix} 1 &5 &7 & 6& 1\\ 2 &1 &10 &4 &4 \\ 3&6 & 7& 5 & 2 \end{bmatrix},對其進行奇異值分解。

import numpy as np
#創建矩陣A
A = np.array([[1,5,7,6,1],[2,1,10,4,4],[3,6,7,5,2]])

#利用np.linalg.svd()函數直接進行奇異值分解
#該函數有三個返回值:左奇異矩陣,所有奇異值,右奇異矩陣。
U,Sigma,VT = np.linalg.svd(A)

#展示
print(U)
print(Sigma)
print(VT)

運行結果:


利用SVD分解、壓縮圖像

原圖:

代碼:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np

img_eg = mpimg.imread("car.jpg")
print(img_eg.shape) #運行結果:(400,640,3)


#將圖片數據轉化爲二維矩陣並對其進行奇異值分解
img_temp = img_eg.reshape(400, 640 * 3)
U,Sigma,VT = np.linalg.svd(img_temp)

# 取前10個奇異值
sval_nums = 10
img_restruct1 = (U[:,0:sval_nums]).dot(np.diag(Sigma[0:sval_nums])).dot(VT[0:sval_nums,:])
img_restruct1 = img_restruct1.reshape(400,640,3)
img_restruct1.tolist()

# 取前50個奇異值
sval_nums = 50
img_restruct2 = (U[:,0:sval_nums]).dot(np.diag(Sigma[0:sval_nums])).dot(VT[0:sval_nums,:])
img_restruct2 = img_restruct2.reshape(400,640,3)

# 取前100個奇異值
sval_nums = 100
img_restruct3 = (U[:,0:sval_nums]).dot(np.diag(Sigma[0:sval_nums])).dot(VT[0:sval_nums,:])
img_restruct3 = img_restruct3.reshape(400,640,3)

#展示
fig, ax = plt.subplots(nrows=1, ncols=3)
ax[0].imshow(img_restruct1.astype(np.uint8))
ax[0].set(title = "10")
ax[1].imshow(img_restruct2.astype(np.uint8))
ax[1].set(title = "50")
ax[2].imshow(img_restruct3.astype(np.uint8))
ax[2].set(title = "100")
plt.show()

運行結果:

可以看到,取前50或100個特徵值即可較好的重構圖片,相對於原來的圖片(400個特徵值)節約了大量空間。


利用SVD分解求超定方程的解

於是對於齊次線性方程\boldsymbol{Ax=0},如果\boldsymbol{A}_{m\times n}列滿秩且m> n,則該方程組爲超定方程組(有效方程個數大於未知參數的個數的方程)。此時的方程組沒有精確解,需要求解最小二乘解。在\left \| \boldsymbol{x} \right \|=1的約束條件下下,其最小二乘解爲矩陣\boldsymbol{A^TA}最小特徵值所對應的特徵向量,根據。

下面我們來以這個思路求解一個非常簡單的超定方程組:

\left\{\begin{matrix} 2x_1+4x_2=11\\ 3x_1-5x_2=3\\ x_1+2x_2=6 \\2x_1+x_2=7\end{matrix}\right.

首先,我們將這個方程組化簡爲\boldsymbol{Ax=0}的格式:

\begin{bmatrix} 2 & 4 &-11\\ 3 & -5 &-3 \\ 1 & 2&-6 \\ 2&1&-7\end{bmatrix}\begin{bmatrix} x_1\\ x_2 \\1\end{bmatrix}=\begin{bmatrix} 0\\ 0\\ 0 \\0\end{bmatrix}

下面是代碼:

import numpy as np
#輸入係數矩陣A
A = np.array([[2,4,-11],[3,-5,-3],[1,2,-6],[2,1,-7]])


#對A進行svd分解
U,Sigma,VT = np.linalg.svd(A)
#print(U)
#print(Sigma)
#print(VT)

#求解,V的列向量即是ATA的特徵向量
#VT最後一行的行向量即爲最小特徵值對應的特徵向量
#由於x[3,0]=1,所以需要對結果進行處理
k=1/ VT[2,2]
x_1=VT[2,0]*k
x_2=VT[2,1]*k
print(x_1,x_2)

#誤差
X=np.array([[x_1],[x_2],[1]])
R=np.dot(np.transpose(np.dot(A,X)),(np.dot(A,X)))
print (R)

運行結果:

解得最小二乘解爲\left\{\begin{matrix} x_1=3.045\\ x_2=1.243 \end{matrix}\right.,誤差平方和 R=0.341


 

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