https://www.cnblogs.com/pinard/p/6251584.html 可参考。
一个 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的转置.