张家界网站建设多少钱长沙seo培训班
当AAA是方阵时,可以很容易地进行特征分解:A=WΣW−1A=W\Sigma W^{-1}A=WΣW−1,其中Σ\SigmaΣ是AAA的特征值组成的对角矩阵。如果WWW由标准正交基组成,则W−1=WTW^{-1}=W^TW−1=WT,特征分解可进一步写成WTΣWW^T\Sigma WWTΣW。
然而,当AAA不是方阵时,情况大不一样了,但仍然可以将AAA表示成A=UΣVTA=U\Sigma V^TA=UΣVT的形式,其中Σ\SigmaΣ也是对角矩阵,对角线上的每个元素被称作奇异值。
奇异值的求解过程和特征值息息相关,因为把AAA变成方阵很简单,只要乘以转置就行。故令L=AATL=AA^TL=AAT,R=ATAR=A^TAR=ATA,则L,RL, RL,R都可以求特征值λi\lambda_iλi和特征向量,其中LLL的特征向量为AAA的左奇异向量,RRR的特征向量为右奇异向量。对应的奇异值σi=λi\sigma_i=\sqrt{\lambda_i}σi=λi。
numpy.linalg
中提供了奇异值分解函数svd
,参数为
svd(a, full_matrices=True, compute_uv=True, hermitian=False)
其中
a
待分解矩阵,维度为(M, N)
full_matrices
若为True
,则U, Vh
分别为(M, M)
和(N, N)
;否则分别为(M, K), (K, N)
,K
为M, N中较小的那个compute_uv
如果为False
则不计算U, Vh
hermitian
为True
时,表示处理的是实对称矩阵
scipy.linalg
中也提供了奇异值分解函数svd
,其参数为
svd(a, full_matrices=True, compute_uv=True, overwrite_a=False, check_finite=True, lapack_driver='gesdd')
其中与numpy.linalg
相同的参数,其意义也相同,不相同的部分,各参数含义如下
overwrite_a
如果为True
,则直接对a
进行修改check_finite
如果为True
,则进行有限性检查lapack_driver
SVD分解的方法,有两个选择'gesdd'
效率更高'gesvd'
此为Matlab和R中使用的方法
其返回值即U,Σ,VTU, \Sigma, V^TU,Σ,VT。
scipy.linalg
还提供了两个和SVD相关的函数,svdvals(a)
用于求a
的奇异值;diagsvd(s, M, N)
通过s, M, N
,创建一个Σ\SigmaΣ矩阵。
下面测试一下svd
import numpy as np
import scipy.linalg as sl
a = np.random.rand(5,5)
u1, s1, vh1 = sl.svd(a)
u2, s2, vh2 = np.linalg.svd(a)
print(s1)
# [2.63698545 0.94063722 0.36159198 0.21052102 0.19014115]
print(s1-s2)
# [ 0.0 0.0 1.11022302e-16 -2.77555756e-17 0.0]
numpy
和scipy
的结果是几乎相同的,下面测试一下不同方法进行奇异值分解的时间
from timeit import timeit
a = np.random.rand(1000,1000)
timeit(lambda:sl.svd(a), number=10)
# 1.870287900000001
timeit(lambda:np.linalg.svd(a), number=10)
# 13.355788999999998
timeit(lambda:sl.svd(a, lapack_driver='gesvd'), number=10)
# 3.873418600000001