使用Python求解特征值、特征向量及奇異值分解(SVD)


 

 

SVD也是對矩陣進行分解,但是和特征分解不同,SVD並不要求要分解的矩陣為方陣。假設我們的矩陣A是一個m×n的矩陣,那么我們定義矩陣A的SVD為:A=UΣVT

其中U是一個m×m的矩陣,Σ是一個m×n的矩陣,除了主對角線上的元素以外全為0,主對角線上的每個元素都稱為奇異值,V是一個n×n的矩陣。U和V都是酉矩陣,即滿足UTU=I,VTV=I。

以下是一個SVD求解過程:

 

 

 
   

 

 

以下是我使用Python實現的SVD求解過程

# -*- coding: utf-8 -*-

"""

Created on Wed Oct 17 13:43:48 2018

 

@author: hanzi5

"""

 

import numpy as np

#import scipy as sc

 

# A=UΣVT

#A=np.mat([[0,1],[1,1],[1,0]])

#A=np.mat([[4,0],[3,5]])

#A=np.mat([[1,0,0,0,2],[0,0,3,0,0],[0,0,0,0,0],[0,4,0,0,0]])

A=np.mat([[4,4],[-3,3]])

#A=np.mat([[4,3],[8,6]])

 

ATA=A.T*A

AAT=A*(A.T)

 

#求解矩陣的特征值、特征向量

lambda1,vector1 = np.linalg.eig(ATA)

lambda2,vector2 = np.linalg.eig(AAT)

 

# 自己計算U、Σ、VT

U=vector2

#sigma=np.mat([[np.sqrt(3),0],[0,1],[0,0]])

#sigma=np.mat([[6.3245,0],[0,3.1622]])

#sigma=np.mat([[4,0,0,0,0],[0,3,0,0,0],[0,0,np.sqrt(5),0,0],[0,0,0,0,0]])

sigma=np.mat([[np.sqrt(32),0],[0,np.sqrt(18)]])

#sigma=np.mat([[np.sqrt(125),0],[0,0]])

VT=vector1.T # 注意需要對V矩陣進行轉置

 

# 使用np自帶包計算U、Σ、VT

U2,S,VT2=np.linalg.svd(A)  

 

# 酉矩陣驗證,兩矩陣乘積為單位陣I

U.T*U

VT.T*VT

 

# 還原矩陣A

U*sigma*VT # 自己計算的結果

U2*sigma*VT2 # np計算結果

 

 

 

以上源代碼中A矩陣我列出了多個,sigma矩陣是我根據A特征值開根號得到的奇異值,沒有找到好的寫法,所有手動把這個矩陣寫出來了。

如果你運行了以上代碼,可能會發現有多個結果U*sigma*VT與原矩陣A不相等,我最終在參考資料2“23、奇異值分解svd”一問中找到了答案,建議大家仔細看看這篇文章。以下引用原文一段作者答疑:

 

當SVD結果的矩陣出現以下這兩種情況時:

1、需要整個矩陣添加相反的正負號才等於原矩陣;

2、SVD求出的矩陣中某一列(多列也一樣)需要添加相反的正負號才等於原矩陣;

以上兩種情況都認為:你求解SVD成功,求的這個SVD和原矩陣一致。

 

解SVD常遇見的疑問

1、需要添加正負符號問題

在例題2中出現了最后的矩陣需要再絕對值才等於原矩陣,或者出現某一列需要添加正負正反的符號才等於原矩陣,

為什么會這樣?

答:原因是你所用的計算軟件對“它”動的毛手毛腳。

我非常肯定這一點。在查閱網上大量相似問題又最后無解,自己在matlab中發現:如果你只是一步一步求解

AA^{T} 或者 A^{T}A ,最后將結果分別依照公式拼湊上去,那么問題就在你求解 AA^{T} 和 A^{T}A 的特征向量時,

計算軟件有時會給某一列添加和你預想結果完全每一個都相反的符號。

所以在最后得出的計算結果中,將會出現某一列或者整個矩陣出現需要添加正負號才等於原矩陣的原因。

但是,這並不干擾你求解SVD的正確性。它給你添加的相反符號也沒有錯。

因為它們本質是“特征向量”,本質是線性或非線性方程的基礎解析,只要它是相應的線性方程組的基礎解析就沒問題。

同一特征值的特征向量的非零線性組合,仍然是這個特征值的特征向量。比如,若 x 是方陣A某個特征值對應的特征向量,

則kx 也是A對應於該特征值的特征向量。(k取正數或者負數,不取0)在之前的章節里,

很清楚得說明白了k是基礎解析的k倍,基礎解析的k倍,無論k幾倍都是某個特征值的特征向量,

它們都存在在一條軸上,一條由同一個方向上各個長短不同的特征向量組成的“旋轉軸”。

所以對某一列向量,或者所有的列向量添加相反的符號(乘於-1),得到的SVD分解結果都是正確的。

但若非整個列向量取相反符號,而是僅僅存在某一個分量有符號問題,那就是你求解中出現了問題。

但是!這種情況卻有一個例外,請參考下一點 2

 

2、“求錯”的地方剛好撞見“轉置”

比如,在麻省理工大學Gilbert Strang教授講的《線性代數》的奇異值分解那一課,他出現錯誤的問題在於,

“求錯”的地方剛好撞見“轉置”,V矩陣正確的符號應該是:

正 負

正 正

他求成了:

正 正

正 負

本來這樣也是沒錯的,因為在1中,我說特征向量kx和x一樣,在上面兩個矩陣中,下面的列2只不過乘於-1就

等於上面的列2,本來是正確的,但是問題就在於,V矩陣最后在SVD公式里需要轉置,而轉置的位置剛好就是將E12變到E21,

將E21變到E12,所以原本在屬於那一列中沒有錯誤的計算,轉置后就錯誤了。解決的方法並不是手解,

我想沒人蠢到用手解解一個"萬階矩陣"吧?有的話請告訴我。。。解決的方法在下一段將出現。

(下一段為:計算軟件求解SVD的要注意的問題)

 

3、其它常見出錯的問題

有可能是V沒有進行轉置:反正我是看到Gilbert Strang教授那一課中,其實不僅沒有發現“錯誤點”在轉置位置,而且,

他還忘了對V進行轉置。(所幸當時那個矩陣轉不轉置兩者都一樣,所以他忘了也沒什么。解錯,這不毫不奇怪,

但可笑是,國內的相關文章上都依照他錯誤的方式去解,不僅沒有解答真正的本質在於轉置位置,

就連V需要轉置這么基礎的也沒有一個人記得。我看過很多文章,大家都生搬硬抄直接將黑板的寫上去,

完全不懷疑他有沒有可能寫錯了。真是讀死書。也怪不得國外有Wolframalpha、Mathpad、Mathematics等等軟件,

國內卻只能在每個軟件的評論區喊着“有沒有中文版?”)

 

有可能是U的符號出現錯誤

在多次實驗當中,我發現如果最后的數字出現了錯誤,那么很可能是因為左乘矩陣出現了問題,

在放到這個SVD的例子當中,SVD的左乘矩陣就是U。

 

也就是可以這么總結:

如果只是列向量的正負出現問題,要么你是在V上出心大意忘了添加某個符號,要么就是你剛好碰上"錯誤點"和"轉置位置";

如果你發現整個SVD結果的矩陣數字都出現問題了,數字都完全不相同了,而且可能正負號都不按規律來,那么,首先檢查左乘矩陣U矩陣的正負符號。

 

計算軟件求解SVD的要注意的問題

首先,用哪一款軟件計算SVD都不是重點,重點是:不要一個一個去求,即是不要去求 AA^{T} 和 AA^{T} ,

然后再一一去求各自的特征向量組成V、U。千萬不要這樣去求!!!

因為有可能出現上面出現常見問題1中描述的,當正確而又不恰當的特征向量的分量出現在V的E12轉置位置時,

有問題出現。所以,我們在用計算軟件求解SVD時,請直接使用求解SVD的命令。而不要一一求解,再自己去組合計算。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM