主元分析和奇异值分解
主元分析或者主成分分析,即PCA(Principal Component Analysis)和奇异值分解,即SVD(Singular Value Decomposition)都是常用的对数据进行预处理进行降维的方法,通常我们认为样本的一个特征为一个维度,即特征向量中的维度,若样本的特征非常非常多,那么对于各种算法来说算起来都是很耗时耗内存的,这时就应该降维,同时要保持大部分原有的信息不丢失。
PCA
主成分分析是一种很常见的降维工具,其目标是在样本数据空间中找到新的坐标轴,即新的正交基,使得原有样本能够映射到新的坐标轴上,我们通常认为方差大的数据才是有用的数据,方差小的数据为噪声数据,则在新的空间选取方差较大的坐标轴,将方差小的坐标轴舍弃掉,这就实现了降维
例如数据有A和B两个特征,若A,B的变化是一样的,则完全可以舍弃掉其中一个。
步骤:输入样本集 D = D= D={ x 1 , x 2 , ⋯ , x m x_1,x_2,\cdots,x_m x1,x2,⋯,xm},每个样本有 d d d个特征,输出为维数为 d ^ , d ^ < d \hat{d},\hat{d}<d d^,d^<d的样本
- 对所有样本进行中心化处理,即使得样本的均值为0。 x i = x i − 1 m ∑ i = 1 m x i x_i=x_i-\frac{1}{m}\sum_{i=1}^mx_i xi=xi−m1∑i=1mxi
- 计算样本的协方差矩阵 R R R,其中 r i j = C o v ( x i , x j ) r_{ij}=Cov(x_i,x_j) rij=Cov(xi,xj)
- 求出协方差矩阵 R R R的所有特征值和特征向量
- 对特征值进行降序排序,取前 d ^ \hat{d} d^个特征值 λ 1 , λ 2 , ⋯ , λ d ^ \lambda_1,\lambda_2,\cdots,\lambda_{\hat{d}} λ1,λ2,⋯,λd^及其对应的特征向量 w 1 , w 2 , ⋯ , w d ^ w_1,w_2,\cdots,w_{\hat{d}} w1,w2,⋯,wd^,这些特征向量便构成映射后的空间的坐标轴
- 对原有样本进行映射 D ^ = D ∗ W \hat{D}=D*W D^=D∗W, D D D为 m ∗ d m*d m∗d矩阵, W W W为 d ∗ d ^ d*\hat{d} d∗d^矩阵
- 特征向量 w i w_i wi即映射后的坐标轴 i ⃗ \vec{i} i,其对于原有数据的方差的贡献率为 λ i ∑ j = 1 m λ j \frac{\lambda_i}{\sum_{j=1}^m \lambda_j} ∑j=1mλjλi
最后的输出维数
d
^
\hat{d}
d^可以根据数据的不同而不同,还可以设置一个阈值,例如
t
=
90
t=90
t=90%,取使下式成立的最小的
d
^
\hat{d}
d^值
∑
i
=
1
d
^
λ
i
∑
i
=
1
d
λ
i
≥
t
\frac{\sum_{i=1}^{\hat{d}}\lambda_i}{\sum_{i=1}^d\lambda_i}\ge t
∑i=1dλi∑i=1d^λi≥t
原理推导:为什么是协方差的特征向量就是新空间的坐标轴呢?特征值越大代表什么?
首先我们的目标是找到新的正交基或者新的坐标轴来映射,并且在该正交基映射后方差最大,即映射后各样本之间的距离足够远。
例如:这个二维数据点映射在蓝色直线上,以该蓝色直线为新的坐标轴
U
1
U_1
U1,这样就可以由2维降到1维,且信息能够最大程度保留。若映射到红色这条线,虽然也是降维,但是数据之间的关系丢失了,信息也丢失了。
所以对于上面的二维数据,我们的目标就是找到一个方向基,使数据映射后的方差有最大值。当然这个只是二维降到一维,若三维降到二维,则还要找到新的方向基,此时就不能仅仅是再找映射后方差最大了,因为方差最大只有一条,那我想方差第二大呢?这也不行,因为这可能只与第一个方向基差一点点,几乎重合,所以我们要想第二个方向基于第一个方向基没有任何相关性,即这两个方向基的协方差为0,形象点就是要正交,加上这个约束条件我们再找方差最大的坐标轴。
- 协方差的定义是 E ( ( x − E ( x ) ( y − E ( y ) ) ) E((x-E(x)(y-E(y))) E((x−E(x)(y−E(y)))
补:这里要补充一下线性代数的理解,矩阵 A A A,向量 x x x,那么 A x = y Ax=y Ax=y,相当于 x x x在 A A A的作用下进行一次变换,更深的理解是以 A A A的行向量为新的基,即为新的坐标轴,在这个新空间里, x x x就表示成 y y y,这就好理解主成分分析里的映射关系了。
这样我们要找的新的空间来映射,这个新的空间就可以表示为一个矩阵 P P P,我们不妨将 P T P^T PT作为新空间的映射矩阵,为什么要转置呢?因为 P T P^T PT的行向量为新的正交基,则 P P P的列向量为新的正交基,而我们最后求出来的 P P P正是由特征向量组成,特征向量就是新的基。
假设数据集有m个样本,d个特征,一般我们喜欢的样本矩阵是
X
X
X是m*d的,但在这里我们需要
X
T
X^T
XT,即d*m的,这样矩阵
X
T
X^T
XT的每一列是一个样本,这样就将样本能通过映射矩阵进行映射,且有下列变化:
P
T
:
d
^
∗
d
(
每
一
行
为
一
个
坐
标
轴
(
基
)
,
有
d
^
行
,
则
映
射
后
维
度
为
d
^
)
X
T
:
d
∗
m
(
每
一
列
为
一
个
样
本
,
每
个
样
本
有
d
个
特
征
)
则
P
T
X
T
将
数
据
集
进
行
映
射
,
大
小
为
d
^
∗
m
为
了
符
合
习
惯
,
我
们
转
置
一
下
大
小
为
m
∗
d
^
,
则
样
本
的
特
征
减
少
d
−
d
^
个
X
^
=
(
P
T
X
T
)
T
=
X
P
,
X
大
小
为
m
∗
d
^
P^T:\hat{d}*d(每一行为一个坐标轴(基),有\hat{d}行,则映射后维度为\hat{d})\\ X^T:d*m(每一列为一个样本,每个样本有d个特征)\\ 则P^TX^T将数据集进行映射,大小为\hat{d}*m\\ 为了符合习惯,我们转置一下大小为m*\hat{d},则样本的特征减少d-\hat{d}个\\ \hat{X}=(P^TX^T)^T=XP,X大小为m*\hat{d}
PT:d^∗d(每一行为一个坐标轴(基),有d^行,则映射后维度为d^)XT:d∗m(每一列为一个样本,每个样本有d个特征)则PTXT将数据集进行映射,大小为d^∗m为了符合习惯,我们转置一下大小为m∗d^,则样本的特征减少d−d^个X^=(PTXT)T=XP,X大小为m∗d^
那么
X
^
\hat{X}
X^就是我们所要求的降维后的数据集,它应该符合上述的要求,即每个数据的方差最大,且数据间没有相关性,即协方差为0,这怎么做到呢?我们要根据此求出
P
P
P出来。
既涉及数据内方差又涉及数据间协方差,协方差矩阵很完美的能够表示出来了。我们的新数据集 X ^ \hat{X} X^每一列就是在某一个坐标轴映射上的值,不妨令 X ^ = [ x ^ 1 , x ^ 2 , ⋯ , x ^ d ^ ] \hat{X}=[\hat{x}_1,\hat{x}_2,\cdots,\hat{x}_{\hat{d}}] X^=[x^1,x^2,⋯,x^d^], x ^ i \hat{x}_i x^i为一个列向量,表示所有样本在坐标轴 U i U_i Ui上的映射值,则 X ^ \hat{X} X^的协方差矩阵为 D , d i j D,d_{ij} D,dij为 C o v ( x ^ i , x ^ j ) Cov(\hat{x}_i,\hat{x}_j) Cov(x^i,x^j),可以看出 D D D是一个对称矩阵,大小为 d ^ ∗ d ^ \hat{d}*\hat{d} d^∗d^,对称轴是方差。
- 上述要求等价于这个协方差矩阵 D D D对角元素最大,则非对角元素值为0。(条件一)
我们回到开始,PCA步骤一做的是数据的中心化,且这一步是必须的,这有什么用呢?就是为了方便求出协方差矩阵!中心化后的数据均值为0,那么无论是求方差还是求协方差,数据都要减去均值,那么正好减去0就相当于不用动了!
假设矩阵为
[
a
1
b
1
a
2
b
2
⋯
⋯
a
d
b
d
]
\begin{bmatrix} a_1 & b_1\\ a_2 & b_2\\ \cdots & \cdots \\ a_d & b_d \\ \end{bmatrix}
⎣⎢⎢⎡a1a2⋯adb1b2⋯bd⎦⎥⎥⎤
对应我们的样本集
X
X
X,为m*d,即每一行代表一个样本,不同字母代表不同特征,对上面矩阵第一列记为
A
A
A,第二列记为
B
B
B,为什么要记列呢,因为我们协方差矩阵算的是列与列之间的协方差,即不同坐标轴之间的协方差。并且该矩阵已经中心化处理,即每一列的均值为0.
则上述矩阵的协方差矩阵为
[
∑
i
=
1
d
a
i
2
∑
i
=
1
d
a
i
∗
b
i
∑
i
=
1
d
a
i
∗
b
i
∑
i
=
1
d
b
i
2
]
\begin{bmatrix} \sum_{i=1}^da_i^2 &\sum_{i=1}^da_i*b_i\\ \sum_{i=1}^da_i*b_i & \sum_{i=1}^db_i^2\\ \end{bmatrix}
[∑i=1dai2∑i=1dai∗bi∑i=1dai∗bi∑i=1dbi2]
这个矩阵可以看到
A
A
A的方差为
∑
i
=
1
d
a
i
2
\sum_{i=1}^d a_i^2
∑i=1dai2,
B
B
B的方差为
∑
i
=
1
d
b
i
2
\sum_{i=1}^db_i^2
∑i=1dbi2,
A
A
A与
B
B
B的协方差为
∑
i
=
1
d
a
i
∗
b
i
\sum_{i=1}^da_i*b_i
∑i=1dai∗bi.
因为中心化之后均值为0那么方差和协方差就是元素值相乘.
并且进一步有公式若矩阵 X X X的大小为m*d,则 1 d X T X \frac{1}{d}X^TX d1XTX就是 X X X的协方差矩阵(要满足数据中心化)
我们回到条件一,记原有数据集为
X
:
m
∗
d
X:m*d
X:m∗d,降维后数据集
X
^
:
m
∗
d
^
\hat{X}:m*\hat{d}
X^:m∗d^,原有数据集协方差矩阵为
R
:
d
∗
d
R:d*d
R:d∗d,降维后数据集协方差矩阵为
D
:
d
^
∗
d
^
D:\hat{d}*\hat{d}
D:d^∗d^。降维变换矩阵为
P
:
d
∗
d
^
P:d*\hat{d}
P:d∗d^有以下变换:
D
=
1
d
^
X
^
T
X
^
=
1
d
^
(
X
P
)
T
(
X
P
)
=
1
d
^
P
T
X
T
X
P
=
P
T
1
d
^
X
T
X
P
=
P
T
R
P
D=\frac{1}{\hat{d}}\hat{X}^T\hat{X}\\ =\frac{1}{\hat{d}}(XP)^T(XP)\\ =\frac{1}{\hat{d}}P^TX^TXP\\ =P^T\frac{1}{\hat{d}}X^TXP\\ =P^TRP
D=d^1X^TX^=d^1(XP)T(XP)=d^1PTXTXP=PTd^1XTXP=PTRP
这里发现要想满足条件一,即协方差矩阵
D
D
D对角元素最大,则非对角元素值为0,不就是要矩阵
R
R
R做特征值分解吗?且协方差矩阵
D
D
D对角线元素就是矩阵
R
R
R的特征值,我们只要去最大的
d
^
\hat{d}
d^个特征值,就可以构成
D
D
D,且降维变换矩阵
P
P
P,就是那
d
^
\hat{d}
d^个最大的特征值对于的特征向量呀!
这里还要补充的是 R R R是个对称矩阵,大小为d*d,那么肯定有d个不相关的特征向量,正好上述能够成立!
自此PCA就推导出来了,我们有原有数据集的协方差矩阵的特征向量作为变换矩阵。
并且特征值越大,则代表映射后的数据方差越大,效果越好,我们以根据特征值大小来比较贡献,当贡献率到达一定阈值时,新数据能够几乎代表原有数据且维度减少。下图则表示20个特征的原有样本的协方差矩阵可以有20个特征向量和特征值,我们只需取前6大的特征值,就能大幅度将原有样本的方差表示出来,将20降维到6。
代码实现:
def loadDataSet(filename):
dataSet = []
fr = open(filename)
for line in fr.readlines():
curLine = line.strip().split('\t')
fltLine = map(float,curLine)
dataSet.append(list(fltLine))
return mat(dataSet)
def pca(dataMat,topNfeat=9999999):
meanVals = mean(dataMat,axis=0) #对列取均值
meanRemoved = dataMat-meanVals #数据中心化
print(shape(meanRemoved))
covMat = cov(meanRemoved,rowvar=0) #协方差矩阵,rowvar=0指以一行为一个样本
print(shape(covMat))
eigVals,eigVects = linalg.eig(mat(covMat)) #特征值和特征向量
eigValInd = argsort(eigVals) #argsort是排序后返回index,升序
eigValInd = eigValInd[:-(topNfeat+1):-1] #从最后一列到topNfeat+1列返回
redEigVects = eigVects[:,eigValInd] #取出相应的特征向量
lowDDataMat = meanRemoved*redEigVects #将原数据进行映射
reconMat = (lowDDataMat*redEigVects.T) + meanVals
return lowDDataMat,reconMat
奇异值分解下一篇再讲