【时间】2018.12.08
【题目】特征值分解和奇异值分解以及使用numpy实现
目录
二、奇异值分解(singular Value Decomposition)
一、特征值分解(EIG)
注意:只有方阵才能进行特征值分解
1.1 定义
如果说一个向量v是方阵A的特征向量,将一定可以表示成下面的形式:
这时候λ就被称为特征向量v对应的特征值,一个矩阵的一组特征向量是一组正交向量。特征值分解是将一个矩阵分解成下面的形式:
其中Q是这个矩阵A的特征向量组成的矩阵,Σ是一个对角阵,每一个对角线上的元素就是一个特征值。首先,要明确的是,一个矩阵其实就是一个线性变换,因为一个矩阵乘以一个向量后得到的向量,其实就相当于将这个向量进行了线性变换。
1.2 在python中实现特征值分解
numpy中的linalg已经实现了ELG,可以直接调用,具体为:
e_vals,e_vecs = np.linalg.eig(a)
输入参数:a为需要分解的方阵
返回:
- e_vals:由特征值构成的向量
- e_vecs:由特征向量构成的矩阵
以下是测试代码:
注意矩阵求逆可以使用np.linalg.inv(a)
【代码】
import numpy as np
a = np.random.randn(4, 4)
e_vals,e_vecs = np.linalg.eig(a)
print('分解得到的形状:\n',e_vals.shape,e_vecs.shape )
print('特征值:\n',e_vals)
print('特征向量矩阵:\n',e_vecs)
smat=np.zeros((4,4))
smat= np.diag(e_vals)
#验证特征值分解
result=np.allclose( a, np.dot(e_vecs, np.dot(smat, np.linalg.inv(e_vecs))))#对比两个矩阵的各个元素,若一致则返回True
print('验证特征值分解:\n',result)
【运行结果】
二、奇异值分解(singular Value Decomposition)
2.1、定义
奇异值分解(singular Value Decomposition),简称SVD,线性代数中矩阵分解的方法。假如有一个矩阵A,对它进行奇异值分解,可以得到三个矩阵:
(情况一)这三个矩阵的大小:
矩阵sigma(即上图U和V中间的矩阵)除了对角元素不为0,其他元素都为0,并且对角元素是从大到小排列的,前面的元素比较大,后面的很多元素接近0。这些对角元素就是奇异值。
(情况二)sigma中有n个奇异值,但是由于排在后面的很多接近0,所以我们可以仅保留比较大的r个奇异值,此时奇异值分解为:
实际应用中,我们仅需保留着三个比较小的矩阵,就能表示A,不仅节省存储量,在计算的时候更是减少了计算量。
2.2 在python中实现奇异值分解
numpy中的linalg已经实现了SVD,可以直接调用,具体为:
U,S,Vh= numpy.linalg.svd(a, full_matrices=True, compute_uv=True)[source]
输入参数:
- a 为要分解的矩阵 ,维数>=2,即(...,M,N)
- full_matrices是bool值,默认为True,此时分解出的U和Vh矩阵的形状分别为 (..., M, M)和(..., N, N),即2.1中的情况一,否则为 (..., M, K)和(..., K, N),这里K = min(M, N),即2.1中的情况二
- compute_uv 也是bool值, 表示除S之外s是否计算U和Vh的值,默认为True,即结果返回3个矩阵
返回值:2.1中的3个矩阵
注意: 无论何种情况,返回的奇异矩阵都只是由奇异值组成的一个向量(而且是省略零值的),如果想要获得对应的奇异矩阵,可以使用np.diag(s)进行构建。详细用法请查阅:https://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.svd.html#numpy.linalg.svd
以下是测试代码:
(1)情况一(默认full_matrices=True)
【代码】
import numpy as np
a = np.random.randn(9, 6)
u, s, vh = np.linalg.svd(a)
print('分解得到矩阵的形状:\n',u.shape,s.shape,vh.shape)
print('奇异值:\n',s)
smat=np.zeros((9,6))
smat[:6,:6]= np.diag(s)
print('奇异矩阵:\n',smat)
#验证奇异值分解
result=np.allclose(a, np.dot(u, np.dot(smat, vh)))#对比两个矩阵的各个元素,若一致则返回True
print(result)
【运行结果】
(2)情况二( full_matrices=False)
【代码】
import numpy as np
a = np.random.randn(9, 6)
u, s, vh = np.linalg.svd(a, full_matrices=False)
print('分解得到矩阵的形状:\n',u.shape,s.shape,vh.shape)
smat = np.zeros((6, 6))
print('奇异值:\n',s)
smat= np.diag(s)
print('奇异矩阵:\n',smat)
#验证奇异值分解
result=np.allclose(a, np.dot(u, np.dot(smat, vh)))#对比两个矩阵的各个元素,若一致则返回True
print(result)
【运行结果】
参考文献
http://www.cnblogs.com/LeftNotEasy/archive/2011/01/19/svd-and-applications.html