讲一下numpy的矩阵特征值分解与奇异值分解

讲⼀下numpy的矩阵特征值分解与奇异值分解1、特征值分解
主要还是调包:
from numpy.linalg import eig
特征值分解:  A = P*B*P T当然也可以写成 A = Q T*B*Q  其中B为对⾓元为A的特征值的对⾓矩阵,P=Q T,
⾸先A得对称正定,然后才能在实数域上分解,
>>> A = np.random.randint(-10,10,(4,4))
>>> A
array([[  6,  9, -10,  -1],
[  5,  9,  5,  -5],
[ -8,  7,  -4,  4],
[ -1,  -9,  0,  6]])
>>> C = np.dot(A.T, A)
>>> C
array([[126,  52,  -3, -69],
[ 52, 292, -73, -80],
[ -3, -73, 141, -31],
[-69, -80, -31,  78]])
>>> vals, vecs = eig(C)
>>> vals
亨润成型机炮筒公司
array([357.33597086, 174.10172008,  8.84429957,  96.71800949])
>>> vecs
array([[-0.28738314, -0.51589436, -0.38221983, -0.71075449],
[-0.87487263,  0.12873861, -0.24968051,  0.39456798],
[ 0.2572149 , -0.69304313, -0.33950158,  0.58161018],
[ 0.29300052,  0.48679627, -0.82237845, -0.02955945]])
故使⽤时应先将特征值转换为矩阵:
空气中取水
>>> Lambda = np.diag(vals)
>>> Lambda
array([[357.33597086,  0.        ,  0.        ,  0.        ],
[  0.        , 174.10172008,  0.        ,  0.        ],
[  0.        ,  0.        ,  8.84429957,  0.        ],
[  0.        ,  0.        ,  0.        ,  96.71800949]])
>>> np.dot(np.dot(vecs, Lambda), vecs.T) # 与C=A.T*A相等
array([[126.,  52.,  -3., -69.],
[ 52., 292., -73., -80.],
[ -3., -73., 141., -31.],
[-69., -80., -31.,  78.]])
>>> np.dot(np.dot(vecs.T, Lambda), vecs)
array([[171.65817919,  45.58778569,  53.20435074,  13.37512137],
[ 45.58778569, 125.15670964,  28.22684299, 134.91290105],
[ 53.20435074,  28.22684299, 129.48789571,  80.5284382 ],
[ 13.37512137, 134.91290105,  80.5284382 , 210.69721545]])
验证了使⽤np中的eig分解为A=P*B*P T⽽不是A=Q T*B*Q,其中P=vecs,
即 C = vecs * np.diag(vals) * vecs.T # 这⾥简写*为矩阵乘法
然后再来看使⽤np中的eig分解出来的vec中⾏向量是特征向量还是列向量是特征向量,只需验证:A*vecs[0] = vals[0]*vecs[0] >>> np.dot(C, vecs[0])
array([-12.84806258, -80.82266859,  6.66283128,  17.51094927])
>>> vals[0]*vecs[0]
array([-102.69233303, -184.34761071, -136.58089252, -253.97814676])
syk-214>>> np.dot(C, vecs[:,0])
array([-102.69233303, -312.62346098,  91.91213634,  104.69962583])
>>> vals[0]*vecs[:, 0]
array([-102.69233303, -312.62346098,  91.91213634,  104.69962583])
后者两个是相等的,故使⽤np中的eig分解出的vecs的列向量是特征向量。
然后我们可以验证P是单位正交矩阵:
>>> np.dot(vecs.T, vecs)
array([[ 1.00000000e+00, -7.13175042e-17, -2.45525952e-18,
2.75965773e-16],
[-7.13175042e-17,  1.00000000e+00,  2.49530948e-17,
-5.58839097e-16],
[-2.45525952e-18,  2.49530948e-17,  1.00000000e+00,
-7.85564967e-17],
[ 2.75965773e-16, -5.58839097e-16, -7.85564967e-17,
1.00000000e+00]])
>>> np.dot(vecs, vecs.T)
array([[ 1.00000000e+00,  2.97888865e-16, -2.68317972e-16,
1.69020590e-16],
[ 2.97888865e-16,  1.00000000e+00, -4.40952204e-18,
-6.24188690e-17],
[-2.68317972e-16, -4.40952204e-18,  1.00000000e+00,羊角钩
-1.13726775e-17],
[ 1.69020590e-16, -6.24188690e-17, -1.13726775e-17,
1.00000000e+00]])
# 可以看到除对⾓元外其他都是⾮常⼩的数
即P T*P = P*P T = E , P T=P-1。事实上,在求解P的过程中就使⽤了施密特正交化过程。
另⼀⽅⾯,我们从数学⾓度来看:
⾸先补充⼀些数学知识:可以看我另⼀篇⽂章:
A = P*B*P-1,其中B为对⾓元素为A的特征值的对⾓阵,P的列向量为特征值对应的特征向量(因为B每⾏乘以P每列)
流氓猫2、奇异值分解
还是调包:
from numpy.linalg import svd
设任意矩阵A是m*n矩阵
奇异值分解:A = U*Σ*V T , 其中U为满⾜U T U=E的m阶(m*m)⾣矩阵,Σ为对⾓线上为奇异值σi其他元素为0的⼴义m*n对⾓阵,V为满⾜V T V=E的n阶(n*n)⾣矩阵
a = np.random.randint(-10,10,(4, 3)).astype(float)
'''
array([[ -9.,  3.,  -7.],
[  4.,  -8.,  -1.],
[ -1.,  6.,  -9.],
[ -4., -10.,  2.]])
'''
In [53]: u, s, vh = np.linalg.svd(a)    # 这⾥vh为V的转置
In [55]: u.shape, s.shape, vh.shape
Out[55]: ((4, 4), (3,), (3, 3))
'''
In [63]: u
Out[63]:
array([[-0.53815289,  0.67354057, -0.13816841, -0.48748749],
[ 0.40133556,  0.1687729 ,  0.78900752, -0.43348888],
[-0.59291924,  0.04174708,  0.59180987,  0.54448603],
[ 0.44471115,  0.71841213, -0.09020922,  0.52723647]])
In [64]: s
Out[64]: array([16.86106528, 11.07993065,  7.13719934])
In [65]: vh
Out[65]:
浮油收集器
array([[ 0.31212695, -0.760911  ,  0.56885078],      [-0.74929793, -0.56527432, -0.3449892 ],
[ 0.58406282, -0.31855829, -0.74658639]]) '''
In [56]: np.allclose(a, np.dot(u[:, :3] * s, vh)) Out[56]: True
# 将s转化为奇异值矩阵
In [60]: smat[:3, :3] = np.diag(s)
In [61]: smat
Out[61]:
array([[16.86106528,  0.        ,  0.        ],
[ 0.        , 11.07993065,  0.        ],
[ 0.        ,  0.        ,  7.13719934],
[ 0.        ,  0.        ,  0.        ]])
# 验证分解的正确性
In [62]: np.allclose(a, np.dot(u, np.dot(smat, vh))) Out[62]: True

本文发布于:2024-09-23 16:20:06,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/277487.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:分解   特征值   矩阵   验证   特征向量   向量
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议