摘要
在本文中我们首先介绍什么是奇异值分解(singular value decomposition, SVD)。我们会给出 SVD 的公式,以及其在Python中的实现。我们也会讨论 SVD 与 主成分分析 (principal component analysis, PCA) 之间的关系。
什么是奇异值分解
SVD 是对矩阵的一种分解方法。对任意的矩阵,我们都可以对其进行 SVD 分解。具体来说,对于任意一个
m
×
n
m \times n
m×n 的矩阵
X
X
X,我们可以将
X
X
X 分解为
X
=
U
Σ
V
T
(1)
X = U \Sigma V^T \tag{1}
X=UΣVT(1)
U
∈
R
m
×
m
,
Σ
∈
R
m
×
n
,
V
∈
R
n
×
n
U \in \mathbb{R}^{m \times m}, \, \Sigma \in \mathbb{R}^{m \times n}, \, V \in \mathbb{R}^{n \times n}
U∈Rm×m,Σ∈Rm×n,V∈Rn×n 。
其中
U
T
U
=
I
m
×
m
,
V
T
V
=
I
n
×
n
U^T U = I_{m \times m}, \, V^T V = I_{n \times n}
UTU=Im×m,VTV=In×n,
Σ
\Sigma
Σ 是一个对角矩阵,
Σ
=
(
σ
1
⋱
0
σ
r
0
0
⋱
0
)
\Sigma = \begin{pmatrix} \sigma_1 \\ & \ddots & & & \text{\huge0} \\ & & \sigma_r \\ & & & 0 & \\ & \text{\huge0} & & & \ddots \\ & & & & & 0 \\ \end{pmatrix}
Σ=⎝⎜⎜⎜⎜⎜⎜⎜⎛σ1⋱0σr00⋱0⎠⎟⎟⎟⎟⎟⎟⎟⎞
这里
σ
1
≥
σ
2
⋯
≥
σ
r
≥
0
\sigma_1 \geq \sigma_2 \cdots \geq \sigma_r \geq 0
σ1≥σ2⋯≥σr≥0。
r
r
r 是矩阵
X
T
X
X^T X
XTX 的秩 (rank)。 并且
σ
i
\sigma_i
σi 为矩阵
X
T
X
X^T X
XTX 的特征值
λ
i
\lambda_i
λi 的开方。即
λ
i
=
σ
i
2
\lambda_i = \sigma_i^2
λi=σi2。
而
V
V
V 是由矩阵
X
T
X
X^T X
XTX 的特征向量为列组成的矩阵。即
V
=
(
v
1
,
v
2
,
⋯
,
v
n
)
V = (v_1, \, v_2, \, \cdots, v_n)
V=(v1,v2,⋯,vn),每一个
v
i
v_i
vi 是一个
m
×
1
m \times 1
m×1 的列向量,
X
T
X
v
i
=
λ
i
v
i
X^T X v_i = \lambda_i v_i
XTXvi=λivi 。这里我们的
v
i
v_i
vi 是归一化的,即每个
v
i
v_i
vi 的模为1。所以
V
V
V 的列向量就是
R
n
\mathbb{R}^n
Rn 空间的一组归一化的正交基向量 (orthonormal basis)。
v
i
T
v
j
=
δ
i
j
=
{
1
,
i
=
j
0
,
i
≠
j
v_i^Tv_j = \delta_{ij} =\begin{cases} 1, i = j \\ 0, i \neq j \end{cases}
viTvj=δij={1,i=j0,i=j。
值得注意的是,如果
r
<
n
r < n
r<n,即如果我们只有
r
r
r 个非零的特征值,我们须要补齐
n
−
r
n - r
n−r 个单位向量,来与原来的
r
r
r 个单位向量(特征向量)组成
n
n
n 个向量 [1]。
我们定义
u
i
=
1
σ
i
X
v
i
\displaystyle u_i = \frac{1}{\sigma_i} X v_i
ui=σi1Xvi,那么每个
u
i
u_i
ui 均为
n
×
1
n \times 1
n×1 的列向量。因为
X
T
X
v
i
=
λ
i
v
i
≠
0
X^TX v_i = \lambda_i v_i \neq \mathbf{0}
XTXvi=λivi=0,故
X
v
i
≠
0
X v_i \neq \mathbf{0}
Xvi=0。
并且,我们有
u
i
T
u
j
=
1
σ
i
σ
j
v
i
T
X
T
X
v
j
=
1
σ
i
σ
j
v
i
T
λ
j
v
j
=
δ
i
j
\displaystyle u_i^T u_j = \frac{1}{\sigma_i \sigma_j} v_i^T X^T X v_j = \frac{1}{\sigma_i \sigma_j} v_i^T \lambda_j v_j = \delta_{ij}
uiTuj=σiσj1viTXTXvj=σiσj1viTλjvj=δij。
我们就验证了 { u 1 , u 2 , ⋯ , u r } \{ u_1, \, u_2, \, \cdots, \, u_r \} {u1,u2,⋯,ur} 是 r r r 维空间的一组基。同样的,如果 r < m r < m r<m,我们可以将这个 r r r 维空间的基向量扩展成 m m m 维空间的基向量。记为 { u 1 , u 2 , ⋯ , u m } \{u_1, \, u_2, \cdots, \, u_m \} {u1,u2,⋯,um},那么以 u 1 , u 2 , ⋯ , u m u_1, \, u_2, \, \cdots, \, u_m u1,u2,⋯,um 为列向量组成的矩阵就为 U U U。
这里须要指出的是,矩阵 X T X X^T X XTX 的秩与矩阵 X X X (或 X T X^T XT)的秩相同,即 r a n k ( X T X ) = r a n k ( X ) = r a n k ( X T ) rank(X^TX) = rank(X) = rank(X^T) rank(XTX)=rank(X)=rank(XT)。因为 r a n k ( X ) ≤ min ( m , n ) rank(X) \leq \min(m, n) rank(X)≤min(m,n),所以 r a n k ( X T X ) ≤ min ( m , n ) rank(X^TX) \leq \min(m, n) rank(XTX)≤min(m,n)。从而我们无须担心由于 r r r 过大而无法补全基向量的情况。关于 r a n k ( X T X ) = r a n k ( X ) rank(X^TX) = rank(X) rank(XTX)=rank(X) 的证明可见附录。
由于 r a n k ( X T X ) = r a n k ( X ) rank(X^TX) = rank(X) rank(XTX)=rank(X),如果 r a n k ( X T X ) = r < n rank(X^TX) = r < n rank(XTX)=r<n,那么当我们用 r r r 个归一化的 X T X X^T X XTX 的特征向量构造 V V V 之后,还要补齐 n − r n - r n−r 个模为 1 的基向量。对于这 n − r n - r n−r 个补齐的基向量 v k , r + 1 ≤ k ≤ n v_k, \, r + 1 \leq k \leq n vk,r+1≤k≤n,我们有 X v k = 0 , r + 1 ≤ k ≤ n X v_k = \mathbf{0}, \, r + 1 \leq k \leq n Xvk=0,r+1≤k≤n。这是因为 v 1 , v 2 , ⋯ , v r v_1, \, v_2, \, \cdots, \, v_r v1,v2,⋯,vr 都不在 X X X 的零空间中,并且 v 1 , v 2 , ⋯ , v r v_1, \, v_2, \, \cdots, \, v_r v1,v2,⋯,vr 形成了一个 r r r 维空间。而 v r + 1 , ⋯ , v n v_{r + 1}, \, \cdots, v_n vr+1,⋯,vn 这 n − r n - r n−r 个基向量均与 v 1 , v 2 , ⋯ , v r v_1, \, v_2, \, \cdots, \, v_r v1,v2,⋯,vr 垂直,所以 v r + 1 , ⋯ , v n v_{r + 1}, \, \cdots, v_n vr+1,⋯,vn 都在 X X X 的零空间中。
接着上面的分析,如果 r < n r < n r<n,我们补齐的基向量 v k + 1 , ⋯ , v n v_{k + 1}, \, \cdots, \, v_n vk+1,⋯,vn 均在 X X X 的零空间中,我们便不能再取 X v j X v_j Xvj 当作 u j u_j uj (如果 U U U 也须要补齐的话)。那这个时候如何选取 u j u_j uj 向量呢?我们要做的很简单,这时候只须要根据已有的 u j , 1 ≤ j ≤ r ≤ m u_j, 1 \leq j \leq r \leq m uj,1≤j≤r≤m,来构造出 m m m 维空间中剩下的 m − r m - r m−r 个基向量,来当作 U U U 的剩下的 m − r m - r m−r 个列向量即可。
左右奇异向量
根据上面的定义,我们称 V V V 的列向量 v i v_i vi 是 X X X 的右奇异向量 (right singular vectors);称 U U U 的列向量是 X X X 的左奇异向量(left singular vectors)。 我们有 v i v_i vi 是矩阵 X T X X^T X XTX 的特征向量; u i u_i ui 是矩阵 X X T X X^T XXT 的特征向量。
并且,如果 X T X v i = λ i v i , λ i > 0 X^T X v_i = \lambda_i v_i, \, \lambda_i > 0 XTXvi=λivi,λi>0,那么 u i = 1 λ i X v i \displaystyle u_i= \frac{1}{\sqrt{\lambda_i}} X v_i ui=λi1Xvi 便是 X X T XX^T XXT 的特征向量,且有 X X T u i = λ i u i XX^T u_i = \lambda_i u_i XXTui=λiui。同样的,如果 u i u_i ui 是矩阵 X X T XX^T XXT 的特征向量, X X T u i = λ i u i , λ i > 0 XX^T u_i = \lambda_i u_i, \, \lambda_i > 0 XXTui=λiui,λi>0,那么 v i = 1 λ i X T u i \displaystyle v_i = \frac{1}{\sqrt{\lambda_i}} X^T u_i vi=λi1XTui 便是矩阵 X T X X^T X XTX 的特征向量,且有 X T X v i = λ i v i X^T X v_i = \lambda_i v_i XTXvi=λivi。
通过上述论述,我们同时也证明了矩阵 X T X X^T X XTX 和 矩阵 X X T XX^T XXT 的非零特征根是一样的。
程序实现
在 Python 中,我们可以用 numpy
中 linalg.svd
来对矩阵进行 SVD 分解。
import numpy as np
from numpy.linalg import svd
from sklearn.decomposition import TruncatedSVD
X = np.array([[1, 2, 3], [2, 4, 2]])
svd(X, full_matrices=True)
(array([[-0.59233648, -0.8056907 ],
[-0.8056907 , 0.59233648]]),
array([5.98022195, 1.49564213]),
array([[-3.68501017e-01, -7.37002033e-01, -5.66599509e-01],
[ 2.53391004e-01, 5.06782008e-01, -8.23993323e-01],
[-8.94427191e-01, 4.47213595e-01, -2.22044605e-16]]))
不确定性
根据之前的分析, 如果
r
<
n
r < n
r<n,我们在确定
V
V
V 的时候须要对
n
n
n 维空间的基向量进行补齐。而这种补齐并不是唯一的。举例来说,在四维空间中,如果我们已经有了两个标准基向量
u
1
=
(
1
0
0
0
)
,
u
2
=
(
0
1
0
0
)
u_1 = \begin{pmatrix} 1 \\ 0 \\ 0 \\ 0 \\ \end{pmatrix}, u_2 = \begin{pmatrix} 0 \\ 1 \\ 0 \\ 0 \\ \end{pmatrix}
u1=⎝⎜⎜⎛1000⎠⎟⎟⎞,u2=⎝⎜⎜⎛0100⎠⎟⎟⎞,
那么我们再补齐的两个归一化基向量可以选择
u
3
=
(
0
0
1
0
)
,
u
4
=
(
0
0
0
1
)
u_3 = \begin{pmatrix} 0 \\ 0 \\ 1 \\ 0 \\ \end{pmatrix}, u_4 = \begin{pmatrix} 0 \\ 0 \\ 0 \\ 1 \\ \end{pmatrix}
u3=⎝⎜⎜⎛0010⎠⎟⎟⎞,u4=⎝⎜⎜⎛0001⎠⎟⎟⎞,
也可以选择
u
3
′
=
(
0
0
2
2
2
2
)
,
u
4
′
=
(
0
0
2
2
−
2
2
)
u_3' = \begin{pmatrix} 0 \\ 0 \\ \frac{\sqrt{2}}{2} \\ \frac{\sqrt{2}}{2} \\ \end{pmatrix}, u_4' = \begin{pmatrix} 0 \\ 0 \\ \frac{\sqrt{2}}{2} \\ -\frac{\sqrt{2}}{2} \\ \end{pmatrix}
u3′=⎝⎜⎜⎛002222⎠⎟⎟⎞,u4′=⎝⎜⎜⎛0022−22⎠⎟⎟⎞。
那么对于 SVD,如果
r
<
n
r < n
r<n,分解也是不确定的。
比如说对于
X
=
(
1
1
1
2
2
2
)
X = \begin{pmatrix} 1 & 1 & 1 \\ 2 & 2 & 2\\ \end{pmatrix}
X=(121212),根据 python 的结果我们有
X = np.array([[1, 1, 1], [2, 2, 2]])
svd(X, full_matrices=True)
(array([[-0.4472136 , -0.89442719],
[-0.89442719, 0.4472136 ]]),
array([3.87298335e+00, 1.40433339e-16]),
array([[-0.57735027, -0.57735027, -0.57735027],
[-0.81649658, 0.40824829, 0.40824829],
[ 0. , -0.70710678, 0.70710678]]))
即
U
=
(
−
0.4472
−
0.8944
−
0.8944
0.4472
)
U = \begin{pmatrix} -0.4472 & -0.8944 \\ -0.8944 & 0.4472 \end{pmatrix}
U=(−0.4472−0.8944−0.89440.4472),
Σ
=
(
15
0
0
0
0
0
)
\Sigma = \begin{pmatrix} \sqrt{15} & 0 & 0 \\ 0 & 0 & 0 \end{pmatrix}
Σ=(1500000),
V
=
(
−
0.5774
−
0.8164
0
−
0.5774
0.4082
−
0.7071
−
0.5774
0.4082
0.7071
)
V = \begin{pmatrix} -0.5774 & -0.8164 & 0 \\ -0.5774 & 0.4082 & -0.7071 \\ -0.5774 & 0.4082 & 0.7071 \\\end{pmatrix}
V=⎝⎛−0.5774−0.5774−0.5774−0.81640.40820.40820−0.70710.7071⎠⎞。
我们也可以选择
V
′
=
(
−
0.5774
1
+
5
4
−
0.1102
−
0.5774
1
−
5
4
0.7558
−
0.5774
−
0.5
−
0.6455
)
V' = \begin{pmatrix} -0.5774 & \frac{1 + \sqrt{5}}{4} & -0.1102 \\ -0.5774 & \frac{1 - \sqrt{5}}{4} & 0.7558 \\ -0.5774 & -0.5 & -0.6455 \\\end{pmatrix}
V′=⎝⎜⎛−0.5774−0.5774−0.577441+541−5−0.5−0.11020.7558−0.6455⎠⎟⎞。
可以验证,这时
U
Σ
V
′
T
U \Sigma V'^T
UΣV′T 依然等于
X
X
X 。
与 PCA 的关系
对于熟悉 PCA [3] 的读者,可以发现 SVD 与 PCA本质是一样的。我们求数据集 X X X 的主成分,实际是对 X X X 进行 SVD 分解,求解 X T X X^T X XTX 的特征向量 (这里假设 X X X 的列向量的均值为0)。
附录
假设
X
∈
R
m
×
n
X \in \mathbb{R}^{m \times n}
X∈Rm×n,要证明
r
a
n
k
(
X
T
X
)
=
r
a
n
k
(
X
)
rank(X^T X) = rank(X)
rank(XTX)=rank(X),我们可以从零空间的角度 [2] 去考虑。如果我们能证明矩阵
X
T
X
X^T X
XTX 的零空间和矩阵
X
X
X 的零空间是相同的,那么我们就证明了
r
a
n
k
(
X
T
X
)
=
r
a
n
k
(
X
)
rank(X^T X) = rank(X)
rank(XTX)=rank(X)。这是因为矩阵
X
T
X
X^T X
XTX 和矩阵
X
X
X 都有
n
n
n 列,所以
r
a
n
k
(
X
)
+
d
i
m
(
n
u
l
l
(
X
)
)
=
n
rank(X) + dim(null(X)) =n
rank(X)+dim(null(X))=n
r
a
n
k
(
X
T
X
)
+
d
i
m
(
n
u
l
l
(
X
T
X
)
)
=
n
rank(X^TX) + dim(null(X^TX)) = n
rank(XTX)+dim(null(XTX))=n 。
这里
d
i
m
(
n
u
l
l
(
X
)
)
dim(null(X))
dim(null(X)) 表示矩阵
X
X
X 的零空间的维度。如果
n
u
l
l
(
X
)
=
n
u
l
l
(
X
T
X
)
null(X) = null(X^T X)
null(X)=null(XTX),即矩阵
X
X
X 与矩阵
X
T
X
X^TX
XTX 的零空间相同,那么它们的维度自然也相同。下面我们就证明矩阵
X
X
X 与矩阵
X
T
X
X^TX
XTX 的零空间相同。
如果
X
w
=
0
X w = \mathbf{0}
Xw=0,那么自然有
X
T
X
w
=
0
X^T X w = \mathbf{0}
XTXw=0。也就是说每一个
n
u
l
l
(
X
)
null(X)
null(X) 的向量都在
n
u
l
l
(
X
T
X
)
null(X^TX)
null(XTX) 之中。所以
n
u
l
l
(
X
)
⊂
n
u
l
l
(
X
T
X
)
null(X) \subset null(X^TX)
null(X)⊂null(XTX)。
另一方面,如果
X
T
X
w
=
0
X^TX w = \mathbf{0}
XTXw=0,那么
w
T
X
T
X
w
=
0
w^T X^TX w = \mathbf{0}
wTXTXw=0。所以
∣
∣
X
w
∣
∣
2
=
0
\vert \vert Xw \vert \vert^2 = 0
∣∣Xw∣∣2=0,即
X
w
=
0
Xw = \mathbf{0}
Xw=0。从而
n
u
l
l
(
X
T
X
)
⊂
n
u
l
l
(
X
)
null(X^TX) \subset null(X)
null(XTX)⊂null(X)。于是
n
u
l
l
(
X
)
=
n
u
l
l
(
X
T
X
)
null(X) = null(X^T X)
null(X)=null(XTX)。
□
\square
□
参考文献
[1] A Tutorial on Principal Component Analysis, Jonathon Shlens, arXiv, 2014
[2] 机器学习:矩阵的秩和矩阵的四个子空间, Matrix_11, CSDN blog
[3] 主成分分析(principal component analysis, PCA)公式, kdaHugh, CSDN blog