基於python 和 matlab的矩陣奇異值分解

一個 mxn的矩陣H可以分解爲 U(mxm) ,S(mxn) , V(nxn) 三個矩陣的乘積,這就是奇異值分解。S是一個對角矩陣,一般從大到小排列,S的元素值稱爲奇異值。
Matlab和python均提供奇異值分解的函數:
Matlab:
>> a = [1,2,3,4;2,3,5,3;6,4,1,3]

a =
     1     2     3     4
     2     3     5     3
     6     4     1     3

>> [u,s,v] = svd(a)

u =
   -0.4614    0.4307   -0.7756
   -0.5933    0.5002    0.6307
   -0.6596   -0.7512   -0.0247
s =
   10.7919         0         0         0
         0    4.4799         0         0
         0         0    1.5702         0
v =
   -0.5194   -0.6866    0.2148   -0.4610
   -0.4949   -0.1435    0.1540    0.8431
   -0.4643    0.6790    0.5106   -0.2503
   -0.5193    0.2165   -0.8182   -0.1186

Python:

import numpy as np       
def xsvd(H):    
    U, S, V = np.linalg.svd(H)  
    print('U:', U )  
    print('S:', S )  
    print('V:', V )  
    return U , S , V   
    
def UxSxV( U , S, V ) :  
    S1 = np.array( [ [S[0] , 0., 0.,0.] ,  
                     [0. , S[1] , 0.,0.] ,  
                     [0. , 0., S[2] ,0.]   
                    ] )  
    m1 = np.dot( U , S1 )  
    m2 = np.dot( m1 , V )  
    print ( m2 )  
    return m2   

def MxMtran(prom , U ) :
    print ( prom ) 
    Ut = np.transpose( U )
    print( Ut )
    I = np.dot( U , Ut )
    print ( I )
  
def main() :  
    H = np.array( [ [1.,2.,3.,4.],  
                 [2.,3.,5.,3.],  
                 [6.,4.,1.,3.]]  
               )  
    u, s , v = xsvd( H )  
    h = UxSxV ( u , s, v )  
    print( h-H < 0.00001 )
    MxMtran( 'U:' ,  u )
    MxMtran('V:' , v)
  
main()  
U: [[-0.46139677  0.4306905  -0.77564084]
 [-0.59330968  0.50021413  0.63068965]
 [-0.65961855 -0.75119339 -0.02473566]]
S: [10.79190564  4.47986284  1.57022343]
V: [[-0.51943815 -0.4949262  -0.46426993 -0.51931253]
 [-0.68663745 -0.14347541  0.67902721  0.21648525]
 [ 0.21482581  0.15401926  0.51062167 -0.81816469]
 [-0.46104544  0.84305453 -0.25028181 -0.11855454]]
[[1. 2. 3. 4.]
 [2. 3. 5. 3.]
 [6. 4. 1. 3.]]
[[ True  True  True  True]
 [ True  True  True  True]
 [ True  True  True  True]]
U:
[[-0.46139677 -0.59330968 -0.65961855]
 [ 0.4306905   0.50021413 -0.75119339]
 [-0.77564084  0.63068965 -0.02473566]]
[[1.00000000e+00 1.49283451e-16 6.66639328e-17]
 [1.49283451e-16 1.00000000e+00 1.64787722e-16]
 [6.66639328e-17 1.64787722e-16 1.00000000e+00]]
V:
[[-0.51943815 -0.68663745  0.21482581 -0.46104544]
 [-0.4949262  -0.14347541  0.15401926  0.84305453]
 [-0.46426993  0.67902721  0.51062167 -0.25028181]
 [-0.51931253  0.21648525 -0.81816469 -0.11855454]]
[[ 1.00000000e+00  7.26923038e-18  2.55496391e-17  1.26776949e-16]
 [ 7.26923038e-18  1.00000000e+00  3.23831057e-17  2.00324633e-16]
 [ 2.55496391e-17  3.23831057e-17  1.00000000e+00 -1.80240893e-16]
 [ 1.26776949e-16  2.00324633e-16 -1.80240893e-16  1.00000000e+00]]

可以看出,奇異值分解之後再相乘可以還原出原矩陣。與matlab不一樣,Python分解出來的S矩陣使用一維數組表示,要矩陣乘的話,需要擴展成代碼中的S1 。相應於python ,Matlab出來的V矩陣是轉置的。Matlab更符合數學書裏的講法:


可以看出, 公式裏的V轉置之後作爲乘數.所以Matlab導出的是V,而Python導出的是V的轉置.


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