前言:
此博客仅仅为了自己复习方便,表述很不严谨,读者要了解PCA,建议直接移步参考文献。
文章目录
一、基本介绍
主成分分析(Principal components analysis),以下简称PCA, 广泛地运用在数据压缩和噪声消除中,是一种很重要的无监督学习算法。
这一方法使用正交变换
, 把由线性相关变量
表示的观测数据转换为少数
几个由线性无关变量
表示的数据,线性无关的变量称为主成分
。
PCA算法包括协方差矩阵的特征值分解
和数据矩阵的奇异值分解
方法。
PCA的目标是:尽可能保留信息地对数据实现降维。
二、方法
基于PCA的目的, 总体来说可以从两个方向进行优化:
(1): 能够最大可能地重构原始数据。参考[1]的小节2。
(2): 使得数据在低维空间差异尽可能大。差异程度用各坐标轴上的方差之和度量。参考[1]的小节3。
两种思路的优化结果完全等价的: 最后的优化目标:
a
r
g
max
W
t
r
(
W
T
X
X
T
W
)
s
.
t
.
W
T
W
=
I
arg \max_{W} tr(W^TXX^TW) \ s.t.W^TW=I
argWmaxtr(WTXXTW) s.t.WTW=I
其中
W
∈
R
K
×
K
′
,
X
∈
R
K
×
N
W \in R^{K \times K'}, X \in R^{K \times N}
W∈RK×K′,X∈RK×N, 其中
K
,
K
′
K, K'
K,K′分别为原空间和降维空间的维度。
值得注意的是,若从第(2)个思路出发, Z = W T X ∈ R K ′ × N Z = W^TX \in R^{K' \times N} Z=WTX∈RK′×N是数据 X X X在降维空间里的投影。很明显降维空间样本在各方向的方差和正比于 t r ( Z Z T ) = t r ( W T X X T W ) tr(ZZ^T)=tr(W^TXX^TW) tr(ZZT)=tr(WTXXTW). 因此凭直觉就可以直接得出优化目标。
最后得到的最优 W ∈ R K × K ′ W \in R^{K \times K'} W∈RK×K′由样本协方差矩阵 S = X X T S=XX^T S=XXT的前 K ′ K' K′大的特征值对应的特征向量组成。
准确来说 S = X X T N − 1 S=\frac{XX^T}{N-1} S=N−1XXT, 但是一个常数因子不影响PCA结果,为了简便,下方认为 S = X X T S = XX^T S=XXT
三、两个步骤
PCA降维实际上可以分为两个步骤。(1) 通过一个正交变换
对原坐标轴进行旋转,(2) 然后去除掉旋转后数据坐标中的一些维度。这在[3]中有比较好的动画展示。
因此我们本质上来说是要寻找一个正交矩阵
W
′
∈
R
K
×
K
W' \in R^{K \times K}
W′∈RK×K, 对数据空间进行旋转操作,求出数据在新空间中的坐标:
W
′
T
X
∈
R
K
×
N
W'^TX \in R^{K \times N}
W′TX∈RK×N, 最后舍弃一些维度。将两个步骤合起来,即进行操作:
W
T
X
∈
R
K
′
×
N
W^TX \in R^{K' \times N}
WTX∈RK′×N,从而实现降维。
对 S S S的特征值进行降序排列: ( λ 1 , λ 2 , . . . , λ K ) (\lambda_1, \lambda_2, ..., \lambda_K) (λ1,λ2,...,λK)
[2]中P301页定理16.1指出: 样本第 k k k主成分 y k \mathbf{y_k} yk 对应着 S S S第 k k k个特征向量,且 v a r ( y k ) = λ k var({\mathbf{y_k}})=\lambda_k var(yk)=λk, 因此这也揭示了特征值大小的物理意义: 衡量了数据在其对应特征向量方向上的信息量大小。
注:要满足 v a r ( y k ) = λ k var({\mathbf{y_k}})=\lambda_k var(yk)=λk 需要 S = X X T N − 1 S = \frac{XX^T}{N-1} S=N−1XXT
无论坐标轴如何旋转,由于个体到坐标轴原点的距离不变,归一化后的数据均值为0, 因此各坐标轴方差之和始终等于样本到原点距离平方之和,要使得方差最大,则选择对应方差大的主成分作为降维后的坐标轴。
四、两个实现方法
1、基于协方差矩阵
由目标推导, 基于样本协方差矩阵 S = X X T S =XX^T S=XXT实现PCA算法过程如下:
输入:
- 样本集 X ∈ R K × N X \in R^{K \times N} X∈RK×N
- 低秩空间维度 K ′ K' K′
过程:
- (1) 对数据进行归一化: x i j = x i j − x ˉ i s i x_{ij} = \frac{x_{ij}-\bar{x}_i}{\sqrt{s_i}} xij=sixij−xˉi. ( x i j x_{ij} xij表示第 j j j个数据的第 i i i个特征)
- (2) 计算样本协方差矩阵 S = X X T S =XX^T S=XXT
- (3) 对 S S S进行特征值分解
- (4) 取前 K ′ K' K′大特征值对应的特征向量、并单位化,得到 W = ( w 1 , w 2 , . . . , w K ′ ) W = (w_1, w_2, ..., w_{K'}) W=(w1,w2,...,wK′)
- (5) 计算主成分变量 y k \mathbf{y_k} yk和原变量 x i \mathbf{x}_i xi的相关关系: ρ ( y k , x i ) = λ k w i k s i \rho(\mathbf{y_k},\mathbf{x_i}) = \frac{\sqrt{\lambda_k}w_{ik}}{\sqrt{s_i}} ρ(yk,xi)=siλkwik
- (6) 计算 k k k个主成分变量对原始变量 x i \mathbf{x}_i xi的贡献率: v i = ρ 2 ( x i , ( y 1 , . . . , y K ′ ) ) = ∑ k = 1 K ′ λ k w i k 2 s i v_i=\rho^2(\mathbf{x}_i,(\mathbf{y}_1,...,\mathbf{y}_{K'})) =\sum_{k=1}^{K'}\frac{\lambda_kw_{ik}^2}{s_i} vi=ρ2(xi,(y1,...,yK′))=∑k=1K′siλkwik2. ( y i 、 y j \mathbf{y_i}、\mathbf{y_j} yi、yj不相关)
- (7) 计算降维后的数据: Y = W T X Y=W^TX Y=WTX
输出:
- 降维后的数据 Y ∈ R K ′ × N Y \in R^{K' \times N} Y∈RK′×N
- 主成分变量和原变量的相关性矩阵 P ∈ R K ′ × K \Rho \in R^{ K' \times K} P∈RK′×K
- k k k个主成分变量对原始变量的贡献率向量: v ∈ R K \mathbf{v} \in R^K v∈RK
2、基于SVD分解
SVD分解原理课参考[4]. 对于样本集
X
∈
R
K
×
N
X \in R^{K \times N}
X∈RK×N, 我们可以对其进行SVD分解:
X
=
U
Σ
V
T
X=U\Sigma V^T
X=UΣVT
其中
U
∈
R
K
×
K
U \in R^{K \times K}
U∈RK×K,
Σ
∈
R
K
×
N
\Sigma \in R^{K \times N}
Σ∈RK×N,
V
∈
R
N
×
N
V \in R^{N \times N}
V∈RN×N. 且
U
T
U
=
I
U^TU = I
UTU=I,
V
T
V
=
I
V^TV=I
VTV=I.
协方差矩阵:
S
=
X
X
T
=
U
Σ
V
T
V
Σ
T
U
T
=
U
Σ
2
U
T
S = XX^T = U \Sigma V^T V \Sigma^T U^T= U \Sigma^2U^T
S=XXT=UΣVTVΣTUT=UΣ2UT
进而:
X
T
X
U
=
U
Σ
2
X^TXU=U\Sigma^2
XTXU=UΣ2
因此 U ∈ R K × K U \in R^{K \times K} U∈RK×K的列向量即是 S S S的特征向量。特征值 λ k = σ k k 2 \lambda_k=\sigma_{kk}^2 λk=σkk2. 基于此,有基于SVD的PCA算法:
输入:
- 样本集 X ∈ R K × N X \in R^{K \times N} X∈RK×N
- 低秩空间维度 K ′ K' K′
过程:
- (1) 对数据进行归一化: x i j = x i j − x ˉ i s i x_{ij} = \frac{x_{ij}-\bar{x}_i}{\sqrt{s_i}} xij=sixij−xˉi. ( x i j x_{ij} xij表示第 j j j个数据的第 i i i个特征)
- (2) 对 X X X进行SVD分解,得到 X = U Σ V T X=U \Sigma V^T X=UΣVT
- (3) 按 σ k k \sigma_{kk} σkk从大到小顺序从 U U U中选取 K ′ K' K′个列向量.
- (4) 对选取的向量进行单位化,得到 W = ( u 1 , u 2 , . . . , u K ′ ) W = (u_1, u_2, ..., u_{K'}) W=(u1,u2,...,uK′)
- (5) 计算主成分变量 y k \mathbf{y_k} yk和原变量 x i \mathbf{x}_i xi的相关关系: ρ ( y k , x i ) = σ k k w i k s i \rho(\mathbf{y_k},\mathbf{x_i}) = \frac{\sigma_{kk}w_{ik}}{\sqrt{s_i}} ρ(yk,xi)=siσkkwik
- (6) 计算 k k k个主成分变量对原始变量 x i \mathbf{x}_i xi的贡献率: v i = ρ 2 ( x i , ( y 1 , . . . , y K ′ ) ) = ∑ k = 1 K ′ σ k k 2 w i k 2 s i v_i=\rho^2(\mathbf{x}_i,(\mathbf{y}_1,...,\mathbf{y}_{K'})) =\sum_{k=1}^{K'}\frac{\sigma_{kk}^2w_{ik}^2}{s_i} vi=ρ2(xi,(y1,...,yK′))=∑k=1K′siσkk2wik2
- (7) 计算降维后的数据: Y = W T X Y=W^TX Y=WTX
输出:
- 降维后的数据 Y ∈ R K ′ × N Y \in R^{K' \times N} Y∈RK′×N
- 主成分变量和原变量的相关性矩阵 P ∈ R K ′ × K \Rho \in R^{ K' \times K} P∈RK′×K
- k k k个主成分变量对原始变量的贡献率向量: v ∈ R K \mathbf{v} \in R^K v∈RK
注: A = A T ∈ R N × N A = A^T \in R^{N \times N} A=AT∈RN×N ⇒ \Rightarrow ⇒ A A A可以对角化 ⇔ \Leftrightarrow ⇔ A A A有 N N N个线性无关特征向量
五、代码
博客完整代码可以参看Github
1、基于协方差矩阵
def PCA_with_CM(X, k):
"""
功能:使用协方差矩阵实现PCA算法
输入:
X: Tensor, (K,N) # 数据矩阵
k: int, (1) # 目标维度
输出:
Y: Tensor, (k,N) # 降维后数据
R: Tensor, (k,K) # Rij表示yi和xi的相关性
v: Tensor, (K) # vi表示所有选择的主成分对xi的贡献率
"""
#(1) 归一化
mean = torch.mean(X, 1).unsqueeze(1) #(K, 1)
var = torch.var(X, 1).unsqueeze(1) #(K, 1)
X = (X - mean) / torch.sqrt(var)
#(2) 计算协方差矩阵
S = X.matmul(X.t()) #(K, K)
#(3) 特征分解
lam, W = torch.eig(S, True)
lam = lam[:, 0]
#(4) 单位化, 并取
M = torch.sqrt(torch.sum(W*W, 0)).unsqueeze(0)
W = W / M
top_k = torch.argsort(-lam)[:k]
W = W[:,top_k] # (K, k)
lam = lam[top_k]
#(5) 计算相关系数
s = torch.diag(S).unsqueeze(0)
R = torch.sqrt(lam).unsqueeze(1) * W.t()/ torch.sqrt(s) #(k, K)
#(6) 计算贡献率
v = torch.sum(R * R, 0) #(K)
#(7) 计算目标数据
Y = W.t().matmul(X)
return Y, R, v
2、基于SVD分解
def PCA_with_SVD(X, k):
"""
功能:使用SVD分解实现PCA算法
输入:
X: Tensor, (K,N) # 数据矩阵
k: int, (1) # 目标维度
输出:
Y: Tensor, (k,N) # 降维后数据
R: Tensor, (k,K) # Rij表示yi和xi的相关性
v: Tensor, (K) # vi表示所有选择的主成分对xi的贡献率
"""
#(1) 归一化
mean = torch.mean(X, 1).unsqueeze(1) #(K, 1)
var = torch.var(X, 1).unsqueeze(1) #(K, 1)
X = (X - mean) / torch.sqrt(var)
#(2) SVD分解
U, Sigma, Vt = torch.svd(X, some=False)
top_k = torch.argsort(-Sigma)[:k]
#(3) 选择topk
W = U[:,top_k] # (K, k)
lam = Sigma[top_k] * Sigma[top_k]
#(4) 计算相关系数
S = X.matmul(X.t())
s = torch.diag(S).unsqueeze(0)
R = torch.sqrt(lam).unsqueeze(1) * W.t()/torch.sqrt(s) #(k, K)
#(5) 计算贡献率
v = torch.sum(R * R, 0) #(K)
#(6) 计算目标数据
Y = W.t().matmul(X)
return Y, R, v
3、基于sklearn库
[5] 中比较详细的描述了使用sklearn
进行PCA
降维的使用方式。
不过遗憾的是sklearn
官方似乎没有提供相关系数矩阵
R
R
R, 和贡献率向量
v
\mathbf{v}
v的计算方式。这里补充他们的计算代码:
from sklearn.decomposition import PCA
pca = PCA(n_components=2, whiten=True)
pca.fit(X)
W = pca.components_ # 组成主成分的特征向量(K', K)
lam_sqrt = np.expand_dims(pca.singular_values_, 1) # 对应主成分特征值的二范数,即对应主成分的奇异值,由于广播机制,因此增加维度
X -= np.mean(X, axis=0) # 求协方差矩阵需要减去均值
s = np.expand_dims(np.diag(X.transpose().dot(X)), 0) # 求方差
R = lam_sqrt * W / np.sqrt(s) # Rij, 第i个主成分yi与xj的相关系数
v = np.sum(R*R, 0) # vj: 所选K' 主成分对xj的贡献率
X_new = pca.transform(X) # 降维后数据
注: sklearn
输入的
X
∈
R
N
×
K
X \in R^{N \times K}
X∈RN×K
六、非线性PCA
待理解
七、概率PCA
待理解
参考资料
- [1] 刘建平Pinard: 主成分分析(PCA)原理总结
- [2] 李航统计学习方法第二版P298.
- [3] Principal Component Analysis
- [4] 刘建平Pinard:SVD分解原理
- [5] 刘建平Pinard: 用scikit-learn学习主成分分析(PCA)
附录
参考资料[1]中推导的疑惑之处:
- 疑惑一: 小节2中,使用 W z i Wz^{i} Wzi得到恢复数据 x ˉ ( i ) \bar{x}^{(i)} xˉ(i)
- 解答: 从过渡矩阵角度理解。新空间的一组基按列向量排列组成 W W W, W是新空间到原始空间的过渡矩阵。
- 疑惑二: 小节2中式(5)->式(6)的推导过程:
- 解答 : 当 B T B^T BT和 A A A同形时, t r ( A B ) = t r ( B A ) tr(AB) = tr(BA) tr(AB)=tr(BA)
- 疑惑三: 小节3中,指出样本 x ( i ) x^{(i)} x(i)在新坐标系中的投影方差为 W T x ( i ) x ( i ) T W W^Tx^{(i)}x^{(i)T}W WTx(i)x(i)TW.
- 解答: 这句话表述错了,原文中的样本应该表述为个体,方差应该是 t r ( W T x ( i ) x ( i ) T W ) tr(W^Tx^{(i)}x^{(i)T}W) tr(WTx(i)x(i)TW)或者 x ( i ) T W W T x ( i ) x^{(i)T}WW^Tx^{(i)} x(i)TWWTx(i), 更严谨的,不可以说一个个体的方差,应该说样本的方差,但是最后的优化目标确实没错。
- 疑惑四:小节4中,作者将样本的协方差矩阵写为 X X T XX^T XXT
- 解答:严格来说,应该是 X X T n − 1 \frac{XX^T}{n-1} n−1XXT, 不过他们特征向量一样,只是特征值有成倍的关系,也不影响结果。
参考资料[2]中推导的疑惑之处:
- 疑惑一: P299, Σ = c o v ( x , x ) = E [ ( x − u ) ( x − u ) T ] \Sigma = cov(\textbf{x}, \textbf{x})=E[(\textbf{x} - \textbf{u})(\textbf{x} - \textbf{u})^T] Σ=cov(x,x)=E[(x−u)(x−u)T]
- 解答: 对随机变量 X X X, c o v ( X , X ) = v a r ( X ) = E [ ( X − u ) 2 ] cov(X,X)=var(X)=E[(X-u)^2] cov(X,X)=var(X)=E[(X−u)2]. c o v ( X , Y ) = E [ ( X − u x ) ( Y − u y ) ] cov(X, Y)=E[(X-u_x)(Y-u_y)] cov(X,Y)=E[(X−ux)(Y−uy)]. 书中, u \textbf{u} u是确定向量, x \textbf{x} x是 m m m维随机变量( x \textbf{x} x中的每一个维度都相当于一个 X X X或 Y Y Y), E E E是对矩阵中的每个元素取均值。
- 疑惑二: P300,式(16.2): E ( y i ) = α i T u E(y_i)=\alpha_i^Tu E(yi)=αiTu
- 解答: E ( X + Y ) = E ( X ) + E ( Y ) E(X+Y) = E(X) + E(Y) E(X+Y)=E(X)+E(Y)
- 疑惑三: P300,式(16.3): v a r ( y i ) = α i T Σ α i var(y_i)=\alpha_i^T\Sigma\alpha_i var(yi)=αiTΣαi
- 解答:
- v a r ( X + Y ) = v a r ( X ) + v a r ( Y ) + 2 c o v ( X , Y ) var(X+Y) = var(X) + var(Y) + 2cov(X,Y) var(X+Y)=var(X)+var(Y)+2cov(X,Y)
- v a r ( a X ) = a 2 v a r ( X ) var(aX) = a^2var(X) var(aX)=a2var(X)
- C o v ( a X , b Y ) = a b C o v ( X , Y ) Cov(aX,bY) = abCov(X,Y) Cov(aX,bY)=abCov(X,Y)
- x T A x = ∑ i ∑ j x i x j A i j \textbf{x}^TA\textbf{x}=\sum_{i}\sum_{j}x_ix_jA_{ij} xTAx=∑i∑jxixjAij
- 疑惑四: P300,式(16.4): c o v ( y i , y j ) = α i T Σ α j cov(y_i, y_j)=\alpha_i^T\Sigma\alpha_j cov(yi,yj)=αiTΣαj
- 解答:
- C o v ( X + Y , Z ) = C o v ( X , Z ) + C o v ( Y , Z ) Cov(X+Y,Z) = Cov(X,Z)+Cov(Y,Z) Cov(X+Y,Z)=Cov(X,Z)+Cov(Y,Z)
- x T A x = ∑ i ∑ j x i x j A i j \textbf{x}^TA\textbf{x}=\sum_{i}\sum_{j}x_ix_jA_{ij} xTAx=∑i∑jxixjAij
- 疑惑五: P308页,计算 k k k个主成分对第 i i i个变量 x i \mathbf{x}_i xi的贡献率: ρ 2 ( x i , ( y 1 , . . . , y k ) ) \rho^2(\mathbf{x}_i,(\mathbf{y}_1,...,\mathbf{y}_{k})) ρ2(xi,(y1,...,yk)).
- 解答: 这是多重相关系数,计算公式可参考这里