聊聊特征分解和SVD分解
Posted 修炼之路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聊聊特征分解和SVD分解相关的知识,希望对你有一定的参考价值。
矩阵分解
矩阵分解
(decomposition,factorization):将矩阵拆分为多个矩阵的乘积的运算。矩阵的分解包括以下几种:
- 特征分解
- SVD分解
- PCA
- QR分解
- LU分解
- 极分解
矩阵分解在数据压缩
、推荐系统
以及NLP
等都有着比较广泛的应用。
特征分解
特征分解
(eigendecomposition):能够将矩阵分解成一组特征向量和特征值,是一种使用最为广泛的矩阵分解。并不是所有的矩阵能够使用矩阵分解,只有方阵(矩阵的行数等于列数)才有特征分解,我们可以使用下面的数学形式来表示特征分解:
A
v
=
λ
v
Av=\\lambda v
Av=λv
上面的式子中,非零向量
v
v
v是矩阵
A
A
A的特征向量,标量
λ
\\lambda
λ是特征向量
v
v
v的特征值
- 特征分解究竟有何作用?
通过特征分解我们能够将一个矩阵分解成为下面的形式:
A = Q Λ Q − 1 A = Q \\Lambda Q^{-1} A=QΛQ−1
上式中的, Q Q Q是矩阵 A A A的特征向量组成的正交矩阵, Λ \\Lambda Λ是一个对角矩阵,每一个对角线元素就是一个特征值,特征值 Λ i , i \\Lambda_{i,i} Λi,i对应的特征向量是矩阵 Q Q Q的第 i i i列,特征值得大小表示对应特征向量对矩阵的重要程度
通过特征分解后,我们就能分析出矩阵中特征向量的重要程度,通过分析特征向量对应特征的大小来判断特征向量的重要性,特征值越大表示特征向量越重要。
奇异值分解
奇异值分解
(singular value decomposition,SVD):将矩阵分解为奇异向量
(singular vector)和奇异值
(singular value),奇异值分解得到的信息和特征分解得到信息是同类型的,相对特征分解来说奇异值分解的应用更为广泛,因为每个实数矩阵都有一个奇异值分解,但不一定有特征分解。因为只有方阵才有特征分解,对于非方阵我们就可以使用奇异值分解。
通过奇异值分解,我们可以将矩阵分解成为下面的形式:
A
=
U
D
V
T
A = U D V^T
A=UDVT
如果
A
A
A是一个
m
×
n
m×n
m×n的矩阵,那么
U
U
U就是一个
m
×
m
m×m
m×m的矩阵,
D
D
D就是一个
m
×
n
m × n
m×n的矩阵,
V
V
V是一个
n
×
n
n×n
n×n的矩阵。
矩阵
U
U
U和
V
V
V是正交矩阵,而矩阵
D
D
D是对角矩阵,矩阵
D
D
D对角线上的元素称为矩阵
A
A
A的奇异值。矩阵
U
U
U的列向量称为左奇异向量
(left singular vector),矩阵
V
V
V的列向量称为右奇异向量
(right singular vector)
我们可以利用特征分解去解释矩阵的奇异值分解,
A
A
A的左奇异向量
是
A
A
T
AA^T
AAT的特征向量,
A
A
A的右奇异向量
是
A
T
A
A^TA
ATA的特征向量。
A
A
A的非零奇异值是
A
A
T
AA^T
AAT特征值的平方根,同时也是
A
T
A
A^TA
ATA特征值的平方根。
除此之外,SVD还可以应用到矩阵求逆到非方阵上来。
伪逆
当我们需要求解一个线性方程的时候:
A
x
=
y
Ax=y
Ax=y
我们可以在等式的左边同时乘以矩阵
A
A
A的逆矩阵
B
B
B后,就可以得到
x
=
B
y
x = By
x=By
这样我们就能够求解线性方程的解。但是,如果矩阵
A
A
A是非方阵,那么它就没有逆矩阵。这时候就只能通过Moore-Penrose 伪逆
来解决这一类问题,矩阵
A
A
A的伪逆的公式如下:
A
+
=
V
D
+
U
T
A^+= V D^+ U^T
A+=VD+UT
上式中的矩阵
U
、
D
、
V
U、D、V
U、D、V是由矩阵
A
A
A通过奇异值分解之后得到的矩阵,对角矩阵
D
D
D的伪逆
D
+
D^+
D+是其非零元素取倒数之后再转置得到的。
当矩阵 A A A的列数多于行数(未知数的个数大于方程个数)时,使用伪逆求解的线性方程可能是众多解法中的一种。当矩阵 A A A的行数多于列数(方程的个数大于未知数的个数)时,方程可能没有解,在这种情况下,通过伪逆得到的 x x x使得 A x Ax Ax和 y y y的欧几里得距离 ∣ ∣ A x − y ∣ ∣ 2 ||Ax-y||_2 ∣∣Ax−y∣∣2最小。
特征分解和奇异值分解的示例
我们可以利用numpy中实现的特征分解
和奇异值分解
来测试一下
- 特征分解
import numpy as np
a = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
#w是特征值,v是特征向量
w,v = np.linalg.eig(a)
print(w)
print(v)
#w[i]对应的特征向量是v[:,i]
print(w[0])
print(v[:,0])
[ 1.61168440e+01 -1.11684397e+00 -1.30367773e-15]
[[-0.23197069 -0.78583024 0.40824829]
[-0.52532209 -0.08675134 -0.81649658]
[-0.8186735 0.61232756 0.40824829]]
16.116843969807043
[-0.23197069 -0.52532209 -0.8186735 ]
通过对矩阵做特征分解
能够很容易通过特征值去判断那些特征向量对矩阵更重要
- SVD分解
import numpy as np
a = np.array([[1,2,3,4],
[4,5,6,7],
[7,8,9,10]])
#SVD奇异值分解
#u左奇异向量矩阵,s奇异值矩阵,vh右奇异向量矩阵
u,s,vh = np.linalg.svd(a)
print(u.shape,s.shape,vh.shape)
#(3, 3) (3,) (4, 4)
print(s)
#[2.11562535e+01 1.55336357e+00 9.06493304e-17]
#通过奇异值向量和奇异值还原矩阵
smat = np.zeros((u.shape[1], vh.shape[0]))
smat[:s.shape[0], :s.shape[0]] = np.diag(s)
restore_a = np.dot(np.dot(u,smat),vh)
# print(restore_a)
#重构矩阵
num = 2
re_a = np.dot(np.dot(u[:,:num],np.diag(s[:num])),vh[:num,:])
print(re_a)
"""
[[ 1. 2. 3. 4.]
[ 4. 5. 6. 7.]
[ 7. 8. 9. 10.]]
"""
利用numpy我们能够很容易的来实现矩阵的奇异值分解
,然后我们也利用了奇异值向量
和奇异值
来还原矩阵。
最后,我们发现我们再重建矩阵的时候只利用两个奇异值和奇异向量也能够完全的还原出原始矩阵,主要是因为第三个奇异值非常的小,对整个矩阵几乎没有影响。
在奇异值矩阵 D D D中,是按照奇异值从大到小排列的,而且矩阵中的奇异值衰减的特别快。在很多情况下,前10%甚至前1%的奇异值之和就占了奇异值之和99%以上。也就是说,我们可以用前r(r远远小于m、n)个奇异值和奇异向量来近似描述矩阵。
以上是关于聊聊特征分解和SVD分解的主要内容,如果未能解决你的问题,请参考以下文章