简介
在UFLDL
中介绍了主成分分析这一块的知识,而且当时学机器学习的时候,老师是将PCA
和SVD
联系起来将的,同时UFLDL
也讲到了使用PCA
做数据白化whitening
处理,这个词经常在论文里面看到。
国际惯例,参考博客:
PRML的第12.1 PCA章节
PCA and SVD explained with numpy
Relationship between SVD and PCA. How to use SVD to perform PCA?
PCA理论
在PRML
中给出了PCA
的两种定义:
- 数据在低维线性空间上的正交投影,这个线性空间被称为主子空间,使得投影数据的方差被最大化
- 平均投影代价最小的线性投影。其中平均投影代价是数据点与投影点之间的平均平方距离。
如下图就是将二维数据投影一维空间 u 1 u_1 u1中
上图中红色的二维数据点被正交投影到主子空间(紫色的线),PCA
的目的就是想让投影后的数据(绿色点)具有最大的方差。 其中正交投影被神乎其神的说了一大堆理论,其实就是投影线垂直于投影面。
通常情况下,我们都是用第一个定义去理解PCA
的,设每个样本都有D
个属性,即D
维向量,总共有N
个样本。
第一步将数据投影到D
维向量
u
1
u_1
u1上,一般来说我们设这个
u
1
u_1
u1是D维空间中的方向向量:
x
^
=
u
1
T
x
\hat{x}=u_1^Tx
x^=u1Tx
第二步求投影方差
1
N
{
u
1
T
x
n
−
u
1
T
x
ˉ
}
2
=
u
1
T
S
u
1
\frac{1}{N}\{u_1^Tx_n-u_1^T\bar{x}\}^2=u_1^TSu_1
N1{u1Txn−u1Txˉ}2=u1TSu1
其中
x
ˉ
\bar{x}
xˉ所有样本均值
x
ˉ
=
1
N
∑
n
=
1
N
x
n
\bar{x}=\frac{1}{N}\sum_{n=1}^Nx_n
xˉ=N1∑n=1Nxn,注意不是每个样本所有属性求均值。
其中
S
S
S是原数据集的协方差矩阵:
S
=
1
N
∑
n
=
1
N
(
x
n
−
x
ˉ
)
(
x
n
−
x
ˉ
)
T
S=\frac{1}{N}\sum_{n=1}^N(x_n-\bar{x})(x_n-\bar{x})^T
S=N1n=1∑N(xn−xˉ)(xn−xˉ)T
【注】协方差反映的是属性与属性之间的关系,而非样本与样本之间的关系。
第三步约束
上面我们经常约束
u
1
u_1
u1是方向向量,那么
u
1
T
u
1
=
1
u_1^Tu_1=1
u1Tu1=1
结合这个约束以及为了让方差最大化的目标,可以利用拉格朗日乘数法建立下式:
u
1
T
S
u
1
+
λ
1
(
1
−
u
1
T
u
1
)
u_1^TSu_1+\lambda_1(1-u_1^Tu_1)
u1TSu1+λ1(1−u1Tu1)
当上式导数为零时,驻点满足
S
u
1
=
λ
1
u
1
Su_1=\lambda_1u_1
Su1=λ1u1
很容易发现
u
1
u_1
u1一定是
S
S
S的特征向量,同时也能发现当
λ
1
\lambda_1
λ1越大,方差越大。所以最大特征值对应的特征向量为第一主成分。同理就能利用特征分解的方法求解到第二、三、…主分量。
综上,可以得到PCA
的一般步骤为:
-
整理原始矩阵 X n × m X_{n \times m} Xn×m ,代表
n
个样本,每个样本维度为m
-
求原始矩阵 X n × m X_{n \times m} Xn×m的协防差阵 S m × m = C o v ( X ) S_{m\times m}=Cov(X) Sm×m=Cov(X)
-
求解协防差阵的特征值和特征向量。
-
选取最大的K(人为给定)个特征值所对应的特征向量组成构成矩阵 W m × k W_{m\times k} Wm×k
-
直接进行矩阵计算,就得到了降维后的数据
Z n × k = X n × m W m × k Z_{n\times k} = X_{n\times m }W_{m\times k } Zn×k=Xn×mWm×k
SVD 理论
一般来说实对称矩阵可以被分解为
A
=
Q
∑
Q
T
A=Q\sum Q^T
A=Q∑QT的形式,其中
Q
Q
Q为标准正交矩阵,
∑
\sum
∑对角阵,对角阵上的元素
λ
i
\lambda_i
λi是矩阵A
的特征值,对应的特征向量是
Q
i
Q_i
Qi
那么如果矩阵
A
A
A为非实对称矩阵的时候,有没有类似的
A
=
U
Σ
V
T
A=U\Sigma V^T
A=UΣVT
奇异值分解(singular value decomposition
,SVD
)做的就是这件事。在SVD
的官方术语中,U
是
(
n
,
n
)
(n,n)
(n,n)维的方阵称为左奇异向量;
Σ
\Sigma
Σ是
(
n
,
m
)
(n,m)
(n,m)的对角阵,对角线上的元素称为奇异值;V
是
(
m
,
m
)
(m,m)
(m,m)维度的方阵称为右奇异向量,并且U
和V
均为单位正交矩阵,
U
U
T
=
1
UU^T=1
UUT=1且
V
V
T
=
1
VV^T=1
VVT=1
求解方法就是利用
A
A
T
AA^T
AAT与
A
T
A
A^TA
ATA都是对称阵的特性,得到:
A
A
T
=
U
Σ
Σ
T
U
T
A
T
A
=
V
Σ
T
Σ
V
T
AA^T=U\Sigma \Sigma ^T U^T \\ A^TA=V\Sigma^T\Sigma V^T
AAT=UΣΣTUTATA=VΣTΣVT
这样就能求解出U
、
Σ
\Sigma
Σ、V。
这篇文章里面有例子。
PCA和SVD的关系
摘自此处,通过协方差矩阵的求解方法建立联系:
在SVD
中:
S
=
A
T
X
=
V
Σ
U
T
U
Σ
V
T
=
V
Σ
2
V
T
=
V
Σ
2
V
−
1
S=A^TX =V\Sigma U^T U\Sigma V^T =V\Sigma ^2V^T =V\Sigma^2V^{-1}
S=ATX=VΣUTUΣVT=VΣ2VT=VΣ2V−1
而在PCA
中:
S
=
u
1
λ
1
u
1
−
1
S=u_1\lambda_1u_1^{-1}
S=u1λ1u1−1
所以:
λ
=
Σ
2
u
=
V
\lambda=\Sigma^2\\ u=V
λ=Σ2u=V
这一点可以通过代码验证:
a=np.array([[1,5,7],[2,3,6],[5,9,3]])
C = np.dot(a.T, a)
eigen_vals,eigen_vecs = np.linalg.eig(C)
u,sigma,v=np.linalg.svd(a,full_matrices=False,compute_uv=True)
print(eigen_vals,sigma**2)
'''
[208.58666048 1.52969164 28.88364788] [208.58666048 28.88364788 1.52969164]
'''
eigen_vecs
'''
array([[-0.34088613, -0.85005392, -0.40150339],
[-0.72034757, 0.51060491, -0.46944862],
[-0.60406625, -0.12919347, 0.78639241]])
'''
v.T
'''
array([[-0.34088613, -0.40150339, -0.85005392],
[-0.72034757, -0.46944862, 0.51060491],
[-0.60406625, 0.78639241, -0.12919347]])
'''
使用PCA对mnist数据集降维
其实在这里遇到一个问题:使用eig对手写数字数据集的协方差矩阵求解特征值时得到了复数特征值和特征向量,这一点暂时没弄明白,但是使用svd
可以得到正常的特征值和特征向量。
sklearn中的pca
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
result = pca.fit_transform(data)
得到结果图
numpy手撕PCA
def PCA_numpy(X):
#零均值化
print(X.shape)
X=X-X.mean(axis=0)
## 使用特征值和特征向量
#协方差矩阵
#cov_X = np.cov(X,rowvar=0)#每一列一个特征
#eig_val,eig_vec = np.linalg.eig(cov_X) #出现复数了
##使用svd
U,eig_val,eig_vec = np.linalg.svd(X)
#选两个最大的
idx = np.argsort(-eig_val)
temp_M=[]
for i in range(2):
temp_M.append(eig_vec[idx[i]])
temp_M = np.array(temp_M).T
result = np.dot(X,temp_M)
return result
同样得到结果值
这个图里面每个颜色代表手写数字数据集里面的0-9数字。
ZCA白化
在UFLDL
中还介绍了基于PCA的白化(whitening
或者球化sphering
)方法,白化的目标有两个:
- 特征之间具有尽量少的相关性
- 特征具有相同的方差
针对第一个目标,前面的使用PCA
降维
x
=
u
T
x
x=u^Tx
x=uTx已经达到了效果。
针对第二个目标,让每个输入特征值都具有单位方差(unit variance
),只需要除以特征值的开根号即可:
x
p
c
a
i
=
x
i
λ
i
x_{pcai}=\frac{x_i}{\sqrt{\lambda _i}}
xpcai=λixi
降维数据的第i
列对应第i
个特征值。这时候,数据的协方差就是单位阵,这就是所说的PCA白化(数据的不同成分无联系并且具有单位方差)。
但是我们第二个目标其实是具有相同方差,而具有相同的单位方差并不是唯一的一个情况,也可能是具有相同的非单位方差。在ZCA
白化中,又对pca白化做了一次左乘:
x
z
c
a
=
u
x
p
c
a
x_{zca}=ux_{pca}
xzca=uxpca
这样虽然把方差不再是1了,但是变换后的数据更加接近原始数据。
有一点需要注意:PCA
可以用于降维(取前面一部分主成分),但是zca
必须保持原有的维度不变,zca
只做去相关,不做降维。
后记
这个学习笔记主要是针对机器学习里面常见的降维方法PCA进行剖析和逐步实现,具体代码包括手写数字的读取和最终降维图的画图,请参看公众号简介中的github网址。后续将持续更新其它机器学习理论和算法,敬请关注: