PCA是机器学习中常用的方法,其主要作用是降维。因为做运算的时候会遇到维度特别大的情况,如果蛮力求解会导致维度灾难。而通过降维可以有效避免这些情况的产生,同时减少运算开销。
要了解PCA首先要了解特征值及特征向量
特征值与特征向量
定义:有一个n * n的矩阵,如果存在一个非零向量xxx使得Ax=λxAx=\lambda xAx=λx,则称标量λ\lambdaλ为特征值(Eigenvalue),而x为特征向量(Eigenvector)。
光看定义其实很抽象,到底大家常说的特征值和特征向量的本质是什么?先看这么一个问题:
某个城镇,每年30%的已婚女性离婚,且20%的单婚女性结婚。假定共有8000名已婚和2000名未婚女性,并且总人口保持不变。我们研究结婚率和离婚率保持不变时将来长时间的期望问题。
首先,很简单,一年后的女性人口比例为:
w1=Aw0=[0.70.20.30.8][80002000]=[60004000]w_1=Aw_0=\begin{bmatrix}
0.7&0.2\\0.3&0.8
\end{bmatrix}\begin{bmatrix}8000\\2000\end{bmatrix}=\begin{bmatrix}6000\\4000\end{bmatrix}
w1=Aw0=[0.70.30.20.8][80002000]=[60004000]如果觉得矩阵看着不太方便的,直接列式计算也是一样。
同理,第二年w2=Aw1=A2w0w_2=Aw_1=A^2w_0w2=Aw1=A2w0
可以用python进行验证以下几个结果
w10=[40045996]w_{10}=\begin{bmatrix}4004\\5996\end{bmatrix}w10=[40045996]
w20=[40006000]w_{20}=\begin{bmatrix}4000\\6000\end{bmatrix}w20=[40006000]
w30=[40006000]w_{30}=\begin{bmatrix}4000\\6000\end{bmatrix}w30=[40006000]
发现过了某个点之后,人口会一直保持不变,(其实这就是个马尔可夫链)。实际上,从w12w_{12}w12之后就一直是[40006000]T\begin{bmatrix}4000&6000\end{bmatrix}^T[40006000]T,并且:
Aw12=[0.70.20.30.8][40006000]=[40006000]Aw_{12}=\begin{bmatrix}0.7&0.2\\0.3&0.8\end{bmatrix}\begin{bmatrix}4000\\6000\end{bmatrix}=\begin{bmatrix}4000\\6000\end{bmatrix}Aw12=[0.70.30.20.8][40006000]=[40006000]
A乘上一个向量,等于这个向量本身,这是不是有点眼熟,正是Ax=λxAx=\lambda xAx=λx 只不过这里的λ=1\lambda=1λ=1
这里还是没有说明特征值到底是什么,接着看。
这个收敛的过程,对任意的人口分布{10000-p, p}都是成立的(p是单身人口),也就是说,无论初始向量是否相等,最后都会得到同样的稳态向量(这里不证明这个,可自行尝试其他初始值)。选择稳态向量的倍数x1=(2,3)Tx_1=(2, 3)^Tx1=(2,3)T作为一个基向量,则:
Ax1=[0.70.20.30.8][23]=[23]=x1
Ax_1=\begin{bmatrix}0.7&0.2\\0.3&0.8\end{bmatrix}\begin{bmatrix}2\\3\end{bmatrix}=\begin{bmatrix}2\\3\end{bmatrix}=x_1Ax1=[0.70.30.20.8][23]=[23]=x1
这里的x1x1x1也是个稳态向量,但是不能把同一个向量的倍数当作第二个向量,所以暂时还只有一个稳态向量。
另外一个稳态向量x2=(−1,1)Tx_2=(-1,1)^Tx2=(−1,1)T同样满足条件使得:
Ax2=[0.70.20.30.8][−11]=[−1212]=12[−11]=12x2Ax_2=\begin{bmatrix}0.7&0.2\\0.3&0.8\end{bmatrix}\begin{bmatrix}-1\\1\end{bmatrix}=\begin{bmatrix}\frac{-1}{2}\\\\\frac{1}{2}\end{bmatrix}=\frac{1}{2}\begin{bmatrix}-1\\1\end{bmatrix}=\frac{1}{2}x_2Ax2=[0.70.30.20.8][−11]=⎣⎡2−121⎦⎤=21[−11]=21x2
于是x1x_1x1 和x2x_2x2就是一对基向量。如果把整个过程看成一个线性变换的话,那么标量1和1/2就是线性变换的自然频率。如果还是不懂,可以把这个结婚离婚的事件看成一个振动过程,无论初始状态如何,最后都会停止,也就是收敛。
只要有振动,就会有特征值,即振动的自然频率。。
主成分分析
主成分分析,Principal Component Analysis,这里的主成分其实就是指最后求到的最大的K个特征值,而这个K是我们想要达到的维度。
其主要步骤如下:
现有数据集X={x1,x2,x3...xn}X=\{x_1,x_2,x_3... x_n\}X={x1,x2,x3...xn},我们打算将数据降到K维度.
1)去掉平均值(中心化)得到新的X
2)计算协方差矩阵1n−1XXT\frac{1}{n-1}XX^Tn−11XXT或者XXTXX^TXXT
3)获得协方差矩阵1n−1XXT\frac{1}{n-1}XX^Tn−11XXT或者XXTXX^TXXT的特征值与特征向量
4)找到最大的K个特征值,将对应的特征向量按行排列成特征向量矩阵P
5)将数据转换到K个特征向量构建的维度中,即Y=PXY=PXY=PX
举个例子
现在有:
X=[−112−1−1−1−122−2]X=\begin{bmatrix}-1&1&2&-1&-1\\
-1&-1&2&2&-2\end{bmatrix}X=[−1−11−122−12−1−2]
由于每一行均值都为0,不需要去平均值,则:
A=XXT=[−112−1−1−1−122−2][−1−11−122−12−1−2]=[84414]A=XX^T=\begin{bmatrix}
-1&1&2&-1&-1\\
-1&-1&2&2&-2\end{bmatrix}\begin{bmatrix}-1&-1\\1&-1\\2&2\\-1&2\\-1&-2\end{bmatrix}=\begin{bmatrix}8&4\\4&14\end{bmatrix}A=XXT=[−1−11−122−12−1−2]⎣⎢⎢⎢⎢⎡−112−1−1−1−122−2⎦⎥⎥⎥⎥⎤=[84414]
获得方阵之后再计算特征值与特征向量,如果给定的X已经是个方阵(n x n)那么可以直接计算特征值,不用计算协方差矩阵。
这里不会按照上面例子中的方式求,直接通过公式Ax=λxAx=\lambda xAx=λx则有
(A−λI)x=0(A-\lambda I)x=0(A−λI)x=0特征方程为:
∣8−λ4414−λ∣=0或λ2−22λ+96=0\left|\begin{array}{cccc}8
-\lambda & 4\\4&14-\lambda\end{array}\right|=0或\lambda ^2-22\lambda +96=0∣∣∣∣8−λ4414−λ∣∣∣∣=0或λ2−22λ+96=0
可得λ1=16\lambda_1 =16λ1=16, λ2=6\lambda_2 =6λ2=6,无论计算中是否有1n−1\frac{1}{n-1}n−11,只会使得特征值按倍数增减,但不会影响特征向量的值以及关于K的选取。
然后继续代回,现在的问题是他们对应的特征向量。
等价于求 (A−16I)x=0(A-16I)x=0(A−16I)x=0 和 (A−6I)x=0(A-6I)x=0(A−6I)x=0 中的x。
这里代入一下可以很快算出两个特征向量分别是
x1=(1,2)T,x2=(2,−1)Tx_1=(1,2)^T, x_2 = (2,-1)^Tx1=(1,2)T,x2=(2,−1)T
因为任意x1,x2x_1,x_2x1,x2的倍数都可以是特征向量,所以标准化之后得:
x1=(15,25)T,x2=(25,−15)Tx_1=(\frac{1}{\sqrt{5}},\frac{2}{\sqrt{5}})^T, x_2=(\frac{2}{\sqrt{5}},-\frac{1}{\sqrt{5}})^Tx1=(51,52)T,x2=(52,−51)T
按列排列,得到特征矩阵:
P=[152525−15]P=\begin{bmatrix}\frac{1}{\sqrt{5}}&\frac{2}{\sqrt{5}}\\\frac{2}{\sqrt{5}}&-\frac{1}{\sqrt{5}}\end{bmatrix}P=[515252−51]
其实到这里,都还是特征值与其向量求解的问题,接下来才是主成分分析。
假如我们想要将数据降到1维,即K=1,从大到小选取第K个特征。
于是,选取λ1\lambda _1λ1对应的特征向量进行计算
y=px=(15,25)[−112−1−1−1−122−2]y=px=(\frac{1}{\sqrt{5}}, \frac{2}{\sqrt{5}})\begin{bmatrix}-1&1&2&-1&-1\\
-1&-1&2&2&-2\end{bmatrix}y=px=(51,52)[−1−11−122−12−1−2]
=(−35,−15,65,35,−55)=(-\frac{3}{\sqrt{5}}, -\frac{1}{\sqrt{5}}, \frac{6}{\sqrt{5}},\frac{3}{\sqrt{5}},-\frac{5}{\sqrt{5}})=(−53,−51,56,53,−55)
这个操作就相当于把X中的坐标点(−1,−1),(1,−1),(2,2),(−1,2),(−1,−2)(-1,-1),(1,-1),(2,2),(-1,2),(-1,-2)(−1,−1),(1,−1),(2,2),(−1,2),(−1,−2)投影到了其中一个基向量上,在这个基向量(也可以叫主元)上的长度分别是−35,−15,65,35,−55-\frac{3}{\sqrt{5}}, -\frac{1}{\sqrt{5}}, \frac{6}{\sqrt{5}},\frac{3}{\sqrt{5}},-\frac{5}{\sqrt{5}}−53,−51,56,53,−55从而实现降维的目的(将二维投影到一维)。
代码验证一下:
import numpy as np
x=np.array([[-1,1,2,-1,-1],[-1,-1,2,2,-2]])
print(np.cov(x))
x_mean=x-np.mean(x)#减平均值
cov=(x_mean@x_mean.T)/(len(x[0])-1) #AAˆT/(n-1)
print(cov)
发现两种方式求出来相同,而我在上面用的AATAA^TAAT正好是这个结果的4倍,也就是(n-1)。继续看特征值与特征向量:
a,b=np.linalg.eig(np.cov(x))
print(a) #eigen value 特征值
print(b) #eigen vector 特征向量
这个特征值1.5和4其实就是对应的6和16,正好(n-1)倍的关系,而同样地,它的特征向量也是把特征值小的放在前面,所以和结果有所出入,并且正负号也有点不同,因为特征向量并不是唯一的。
如果同样把特征值小的放前面,并且都取负,则:
P=[−25−1515−25]P=\begin{bmatrix}-\frac{2}{\sqrt{5}}&-\frac{1}{\sqrt{5}}\\\frac{1}{\sqrt{5}}&-\frac{2}{\sqrt{5}}\end{bmatrix}P=[−5251−51−52]
这就正好对应代码结果,可以演算一下−25-\frac{2}{\sqrt{5}}−52就等于-0.89442719。
验证一下PCA:
from sklearn.decomposition import PCA
pca=PCA(n_components=1)
pca.fit(x.T)
print(pca.transform(x.T))
n_components设为1及以上时,表示要达到的维度,如果设为(0,1]区间的数,表示主成分要达到的比例。
结果如下:
这就对应着降维(投影)之后的在基向量上的长度:
−35,−15,65,35,−55-\frac{3}{\sqrt{5}}, -\frac{1}{\sqrt{5}}, \frac{6}{\sqrt{5}},\frac{3}{\sqrt{5}},-\frac{5}{\sqrt{5}}−53,−51,56,53,−55
至此,PCA的一些基本介绍大致完成,关于其他的一些推导证明问题暂不讨论,实际上sklearn中PCA的实现是基于SVD(奇异值分解)的,后面会继续探讨。